Fishnet 2.0.1
Framework for Graph-Based Analysis of GIS Vector Data
Loading...
Searching...
No Matches
JSONFileAdjacency.hpp
Go to the documentation of this file.
1#include <fstream>
2#include <string_view>
3#include <filesystem>
4#include <nlohmann/json.hpp>
8
9namespace fishnet::graph{
10
11template<typename BaseContainer> requires AdjacencyContainer<BaseContainer,typename BaseContainer::node_type>
12class JSONFileAdjacency : public AdjacencyContainerDecorator<BaseContainer>{
13private:
14 constexpr static std::string_view NODES_KEY = "nodes";
15 constexpr static std::string_view EDGES_KEY = "edges";
16 constexpr static std::string_view NODE_ID_KEY = "id";
17 constexpr static std::string_view NODE_DATA_KEY = "data";
18 using N = typename BaseContainer::node_type;
20 std::filesystem::path filePath;
23
24 void load() {
25 std::ifstream file(filePath);
26 if(not file.is_open() || std::filesystem::is_empty(filePath)){
27 return;
28 }
29 nlohmann::json j;
30 file >> j;
31 file.close();
32 if(not j.contains(NODES_KEY) or not j.contains(EDGES_KEY)){
33 throw std::runtime_error("Invalid JSON format: missing nodes or edges key");
34 }
35 std::unordered_map<size_t,N> idToNodeMap;
36 for(const auto & jsonNode: j[NODES_KEY]){
37 if(not jsonNode.contains(NODE_ID_KEY) or not jsonNode.contains(NODE_DATA_KEY)){
38 throw std::runtime_error("Invalid JSON format: node missing id or data key");
39 }
40 size_t nodeID = jsonNode[NODE_ID_KEY].get<size_t>();
41 N node = fromJson(jsonNode[NODE_DATA_KEY]);
42 this->addNode(std::move(node));
43 idToNodeMap.emplace(nodeID, node);
44 }
45 for(const auto & jsonEdge: j[EDGES_KEY]){
46 if(not jsonEdge.contains("from") or not jsonEdge.contains("to")){
47 throw std::runtime_error("Invalid JSON format: edge missing from or to key");
48 }
49 size_t fromID = jsonEdge["from"].get<size_t>();
50 size_t toID = jsonEdge["to"].get<size_t>();
51 if(not idToNodeMap.contains(fromID) or not idToNodeMap.contains(toID)){
52 throw std::runtime_error("Invalid JSON format: edge references unknown node id");
53 }
54 this->addAdjacency(idToNodeMap.at(fromID), idToNodeMap.at(toID));
55 }
56 }
57
58 void save() const noexcept {
59 nlohmann::json j;
60 j[NODES_KEY] = nlohmann::json::array();
61 size_t ID = 0;
62 std::unordered_map<N,size_t,typename BaseContainer::hash_function,typename BaseContainer::equality_predicate> nodeToIDMap;
63 for(const auto & node: this->nodes()){
64 nlohmann::json jsonNode;
65 size_t nodeID = ID++;
66 nodeToIDMap[node] = nodeID;
67 jsonNode[NODE_ID_KEY] = nodeID;
68 jsonNode[NODE_DATA_KEY] = toJson(node);
69 j[NODES_KEY].push_back(jsonNode);
70 }
71 j[EDGES_KEY] = nlohmann::json::array();
72 for(const auto &[from,to]: this->getAdjacencyPairs()){
73 nlohmann::json edge;
74 edge["from"] = nodeToIDMap.at(from);
75 edge["to"] = nodeToIDMap.at(to);
76 j[EDGES_KEY].push_back(edge);
77 }
78 std::ofstream file(filePath);
79 if(file.is_open()){
80 file << j.dump();
81 file.close();
82 }
83 }
84
85public:
86
87 JSONFileAdjacency(BaseContainer && baseContainer, const std::filesystem::path & filePath, util::UnaryFunction<N, nlohmann::json> auto toJson, util::UnaryFunction<nlohmann::json, N> auto fromJson)
88 : AdjacencyContainerDecorator<BaseContainer>(std::move(baseContainer)), filePath(fishnet::util::PathHelper::absoluteCanonical(filePath)), toJson(std::move(toJson)), fromJson(std::move(fromJson)) {
89 if(not this->filePath.has_extension() or this->filePath.extension() != ".json"){
90 throw std::invalid_argument("File path must have .json extension");
91 }
92 load();
93 }
94
96 save();
97 }
98};
99}
100
101
A decorator for adjacency containers that adds additional functionality.
Definition AdjacencyContainerDecorator.hpp:16
auto getAdjacencyPairs() const noexcept
Definition AdjacencyContainerDecorator.hpp:86
auto nodes() const noexcept
Definition AdjacencyContainerDecorator.hpp:82
void addAdjacency(const N &from, const N &to)
Definition AdjacencyContainerDecorator.hpp:30
bool addNode(const N &node)
Definition AdjacencyContainerDecorator.hpp:42
Definition JSONFileAdjacency.hpp:12
JSONFileAdjacency(BaseContainer &&baseContainer, const std::filesystem::path &filePath, util::UnaryFunction< N, nlohmann::json > auto toJson, util::UnaryFunction< nlohmann::json, N > auto fromJson)
Definition JSONFileAdjacency.hpp:87
~JSONFileAdjacency()
Definition JSONFileAdjacency.hpp:95
Definition FunctionalConcepts.hpp:9
Definition AdjacencyContainer.hpp:4
std::function< R(const T &)> UnaryFunction_t
Definition FunctionalConcepts.hpp:12
Definition BFSClustering.hpp:5
STL namespace.