8ea6e843be08beaa3b2b5feafba6759514f2e20a
[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
94 # A JsonStore can save and load json data from file system.
95 class JsonStore
96
97 # Directory where data are stored.
98 #
99 # Directory is created lazilly at the first write.
100 var store_dir: String
101
102 # Delete all stored data.
103 #
104 # Warning: all `JsonStore` instances sharing the same `store_dir` will
105 # be cleared.
106 fun clear do
107 if not store_dir.file_exists then return
108 store_dir.rmdir
109 end
110
111 # Is there data are stored under `key`.
112 fun has_key(key: String): Bool do
113 return (store_dir / "{key}.json").file_exists
114 end
115
116 # Save `json` object under `key`.
117 fun store_object(key: String, json: JsonObject) do
118 store_json(key, json)
119 end
120
121 # Save `json` array under `key`.
122 fun store_array(key: String, json: JsonArray) do
123 store_json(key, json)
124 end
125
126 # Save `json` data under `key`.
127 #
128 # Only `JsonObject` and `JsonArray` are allowed in a json file.
129 # Use `store_object` or `store_array` instead.
130 private fun store_json(key: String, json: Jsonable) do
131 var path = store_dir / "{key}.json"
132 path.dirname.mkdir
133 var file = new OFStream.open(path)
134 file.write(json.to_json)
135 file.close
136 end
137
138 # Load a JsonObject associated to `key` from store.
139 fun load_object(key: String): JsonObject do
140 return load_json(key).as(JsonObject)
141 end
142
143 # Load a JsonArray associated to `key` from store.
144 fun load_array(key: String): JsonArray do
145 return load_json(key).as(JsonArray)
146 end
147
148 # Load a JsonObject associated to `key` from store.
149 #
150 # Ensure `has_data(key)`
151 private fun load_json(key: String): nullable Jsonable do
152 assert has_key(key)
153 var path = store_dir / "{key}.json"
154 var file = new IFStream.open(path)
155 var text = file.read_all
156 file.close
157 return text.parse_json
158 end
159
160 # Get the list of keys stored under the collection `key`.
161 fun list_collection(key: String): JsonArray do
162 var res = new JsonArray
163 var coll = (store_dir / "{key}").to_path
164 if not coll.exists or not coll.stat.is_dir then return res
165 for file in coll.files do
166 if file.to_s.has_suffix(".json") then
167 res.add(file.to_s.basename(".json"))
168 end
169 end
170 return res
171 end
172
173 # Does `key` matches a collection?
174 fun has_collection(key: String): Bool do
175 var path = (store_dir / "{key}").to_path
176 return path.exists and path.stat.is_dir
177 end
178 end