b8ce0f9a10da3738b3fe851064d876ccfaa8b2d9
[nit.git] / lib / json / store.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # This file is free software, which comes along with NIT. This software is
4 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
5 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
6 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
7 # is kept unaltered, and a notification of the changes is added.
8 # You are allowed to redistribute it and sell it, alone or is a part of
9 # another product.
10
11 # Store and load json data.
12 #
13 # This simple system can be used to store and retrieve json data.
14 #
15 # ## Usage
16 #
17 # ### Initialization
18 #
19 # JsonStore use the file system to store and load json files.
20 #
21 # For initialization you need to give the directory used in the
22 # file system to save objects.
23 #
24 # ~~~
25 # var store = new JsonStore("store_dir")
26 # ~~~
27 #
28 # ### Documents
29 #
30 # With JsonStore you manage *documents*.
31 # Documents are simple json files that can be stored and loaded from json store.
32 #
33 # JsonStore can store documents of type JsonObject and JsonArray.
34 # ~~~
35 # var red = new JsonObject
36 # red["name"] = "red"
37 # red["code"] = "FF0000"
38 # ~~~
39 #
40 # Data are stored under a *key*.
41 # This is the path to the document from `JsonStore::store_dir`
42 # without the `.json` extension.
43 #
44 # Examples:
45 #
46 # * key `document` will store data under `store_dir / "document.json"`
47 # * key `collection/data` will store data under `store_dir / "collection/data.json"`
48 #
49 # ~~~
50 # var key = "colors/red"
51 # ~~~
52 #
53 # Store the object.
54 # ~~~
55 # store.store_object(key, red)
56 # ~~~
57 #
58 # Load the object.
59 # ~~~
60 # assert store.has_key(key)
61 # var obj = store.load_object(key)
62 # assert obj["name"] == obj["name"]
63 # ~~~
64 #
65 # ### Collections
66 #
67 # A collection is a set of documents stored under the same path.
68 #
69 # ~~~
70 # var green = new JsonObject
71 # green["name"] = "green"
72 # green["code"] = "00FF00"
73 # store.store_object("colors/green", green)
74 #
75 # assert store.has_collection("colors")
76 #
77 # var col = store.list_collection("colors")
78 # assert col.length == 2
79 # assert col.has("green")
80 # assert col.has("red")
81 # ~~~
82 #
83 # ### Clearing store
84 #
85 # You can delete all the data contained in the `JsonStore::store_dir` with `clear`.
86 #
87 # ~~~
88 # store.clear
89 # ~~~
90 module store
91
92 import static
93 import json
94
95 # A JsonStore can save and load json data from file system.
96 class JsonStore
97
98 # Directory where data are stored.
99 #
100 # Directory is created lazilly at the first write.
101 var store_dir: String
102
103 # Delete all stored data.
104 #
105 # Warning: all `JsonStore` instances sharing the same `store_dir` will
106 # be cleared.
107 fun clear do
108 if not store_dir.file_exists then return
109 store_dir.rmdir
110 end
111
112 # Is there data are stored under `key`.
113 fun has_key(key: String): Bool do
114 return (store_dir / "{key}.json").file_exists
115 end
116
117 # Save `json` object under `key`.
118 fun store_object(key: String, json: JsonObject) do
119 store_json(key, json)
120 end
121
122 # Save `json` array under `key`.
123 fun store_array(key: String, json: JsonArray) do
124 store_json(key, json)
125 end
126
127 # Save `json` data under `key`.
128 #
129 # Only `JsonObject` and `JsonArray` are allowed in a json file.
130 # Use `store_object` or `store_array` instead.
131 private fun store_json(key: String, json: Jsonable) do
132 var path = store_dir / "{key}.json"
133 path.dirname.mkdir
134 var file = new FileWriter.open(path)
135 file.write(json.to_json)
136 file.close
137 end
138
139 # Load a JsonObject associated to `key` from store.
140 fun load_object(key: String): JsonObject do
141 return load_json(key).as(JsonObject)
142 end
143
144 # Load a JsonArray associated to `key` from store.
145 fun load_array(key: String): JsonArray do
146 return load_json(key).as(JsonArray)
147 end
148
149 # Load a JsonObject associated to `key` from store.
150 #
151 # Ensure `has_data(key)`
152 private fun load_json(key: String): nullable Jsonable do
153 assert has_key(key)
154 var path = store_dir / "{key}.json"
155 var file = new FileReader.open(path)
156 var text = file.read_all
157 file.close
158 return text.parse_json
159 end
160
161 # Get the list of keys stored under the collection `key`.
162 fun list_collection(key: String): JsonArray do
163 var res = new JsonArray
164 var coll = (store_dir / "{key}").to_path
165 if not coll.exists or not coll.stat.is_dir then return res
166 for file in coll.files do
167 if file.to_s.has_suffix(".json") then
168 res.add(file.to_s.basename(".json"))
169 end
170 end
171 return res
172 end
173
174 # Does `key` matches a collection?
175 fun has_collection(key: String): Bool do
176 var path = (store_dir / "{key}").to_path
177 return path.exists and path.stat.is_dir
178 end
179 end