Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifndef GRAFCYTOWAN_CITATION_GRAPH_H
- #define GRAFCYTOWAN_CITATION_GRAPH_H
- #include <vector>
- #include <memory>
- #include <set>
- #include <map>
- class PublicationNotFound : public std::exception {
- const char *what() const noexcept override {
- return "PublicationNotFound";
- }
- };
- class PublicationAlreadyCreated : public std::exception {
- const char *what() const noexcept override {
- return "PublicationAlreadyCreated";
- }
- };
- class TriedToRemoveRoot : public std::exception {
- const char *what() const noexcept override {
- return "TriedToRemoveRoot";
- }
- };
- template <class Publication>
- class CitationGraph {
- private:
- struct Node {
- std::set<std::shared_ptr<Node>> children;
- std::set<std::weak_ptr<Node>, std::owner_less<Node>> parents;
- Publication publication;
- Node(Publication::id_type const &publication)
- : publication(publication) {
- }
- }
- using std::map<Publication::id_type, std::weak_ptr<Node>> = mapType
- std::shared_ptr<Node> root;
- std::shared_ptr<mapType> publications;
- public:
- CitationGraph(Publication::id_type const &stem_id) {
- publications = std::make_shared<mapType>();
- root = std::make_shared<Node>(stem_id);
- }
- CitationGraph(const CitationGraph<Publication> &other) = delete;
- CitationGraph<Publication>& operator=(const CitationGraph<Publication> &other) = delete;
- CitationGraph(CitationGraph<Publication> &&other) noexcept {
- *this = std::move(other);
- }
- CitationGraph<Publication>& operator=(CitationGraph<Publication> &&other) {
- swap(root, other.root);
- swap(publications, other.publications);
- return *this;
- }
- Publication::id_type get_root_id() const noexcept(noexcept(std::declval<Publication>().get_id())) {
- return root->publication.get_id();
- }
- std::vector<Publication::id_type> get_children(Publication::id_type const &id) const {
- if (!exists(id))
- throw PublicationNotFound();
- std::vector<Publication::id_type> ret;
- std::shared_ptr<Node> foundNode = publications->at(id).lock();
- for (std::shared_ptr<Node> child: children)
- ret.emplace_back(child->publication.get_id());
- return ret;
- }
- std::vector<Publication::id_type> get_parents(Publication::id_type const &id) const {
- if (!exists(id))
- throw PublicationNotFound();
- std::vector<Publication::id_type> ret;
- std::shared_ptr<Node> foundNode = publications->at(id).lock();
- for (std::shared_ptr<Node> parent: parents)
- if (!parent.expired())
- ret.emplace_back(parent.lock()->publication.get_id());
- return ret;
- }
- bool exists(Publication::id_type const &id) const {
- auto foundNode = publications->find(id);
- return foundNode != publications.end() && !(foundNode->second.expired());
- }
- Publication& operator[](Publication::id_type const &id) const {
- if (!exists(id))
- throw PublicationNotFound();
- return publications->find(id).second.lock()->publication;
- }
- // TODO
- // void create(Publication::id_type const &id, Publication::id_type const &parent_id);
- // void create(Publication::id_type const &id, std::vector<Publication::id_type> const &parent_ids);
- // TODO
- void add_citation(Publication::id_type const &child_id, Publication::id_type const &parent_id) {
- if (!exists(child_id) || !exists(parent_id))
- throw PublicationNotFound();
- shared_ptr<Node> childNode = publications.find(child_id)->second.lock();
- shared_ptr<Node> parentNode = publications.find(parent_id)->second.lock();
- auto insertParent = childNode->parents.insert(parentNode);
- try {
- parentNode->children.insert(childNode);
- } catch (...) {
- if (insertParent.second)
- childNode->publications.erase(insertParent.first);
- }
- }
- void remove(Publication::id_type const &id) {
- if (!exists(id))
- throw PublicationNotFound();
- if (root->publication.get_id())
- throw TriedToRemoveRoot();
- std::weak_ptr<Node> nodeToRemove = publications.find(id)->second;
- std::shared_ptr<Node> nodeToRemoveShared = nodeToRemove.lock();
- for (const std::weak_ptr<Node> &parent : nodeToRemoveShared->parents) {
- if (!parent.expired())
- parent.lock()->parentShared->children.erase(nodeToRemoveShared);
- }
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement