Merge: Prepare for the android UI module
[nit.git] / lib / android / shared_preferences / shared_preferences_api10.nit
1 # This file is part of NIT (http://www.nitlanguage.org).
2 #
3 # Copyright 2014 Frédéric Vachon <fredvac@gmail.com>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Services to save/load data using `android.content.SharedPreferences` for the android platform
18 module shared_preferences_api10
19
20 import native_app_glue
21 import serialization
22 private import json_serialization
23
24 in "Java" `{
25 import android.content.SharedPreferences;
26 import android.content.Context;
27 import android.app.Activity;
28 import java.util.Map;
29 import java.util.Iterator;
30 import java.lang.ClassCastException;
31 import java.lang.NullPointerException;
32 `}
33
34 extern class NativeSharedPreferences in "Java" `{ android.content.SharedPreferences `}
35 super JavaObject
36 redef type SELF: NativeSharedPreferences
37
38 fun contains(key: JavaString): Bool in "Java" `{ return recv.contains(key); `}
39 fun get_all: HashMap[JavaString, JavaObject] import HashMap[JavaString, JavaObject],
40 HashMap[JavaString, JavaObject].[]= in "Java" `{
41 Map<String, ?> java_map = null;
42 int nit_hashmap = new_HashMap_of_JavaString_JavaObject();
43 try {
44 java_map = recv.getAll();
45 } catch (NullPointerException e) {
46 return nit_hashmap;
47 }
48
49 for (Map.Entry<String, ?> entry: java_map.entrySet())
50 HashMap_of_JavaString_JavaObject__index_assign(nit_hashmap,
51 entry.getKey(), entry.getValue());
52
53 return nit_hashmap;
54 `}
55 fun get_boolean(key: JavaString, def_value: Bool): Bool in "Java" `{
56 boolean return_value;
57 try {
58 return_value = recv.getBoolean(key, def_value);
59 } catch (ClassCastException e) {
60 return def_value;
61 }
62
63 return return_value;
64 `}
65 fun get_float(key: JavaString, def_value: Float): Float in "Java" `{
66 float return_value;
67 try {
68 return_value = recv.getFloat(key, (float) def_value);
69 } catch (ClassCastException e) {
70 return def_value;
71 }
72
73 return return_value;
74 `}
75 fun get_int(key: JavaString, def_value: Int): Int in "Java" `{
76 int return_value;
77 try {
78 return_value = recv.getInt(key, (int)def_value);
79 } catch (ClassCastException e) {
80 return def_value;
81 }
82
83 return return_value;
84 `}
85 fun get_long(key: JavaString, def_value: Int): Int in "Java" `{
86 long return_value;
87 try {
88 return_value = recv.getLong(key, def_value);
89 } catch (ClassCastException e) {
90 return def_value;
91 }
92
93 return (int) return_value;
94 `}
95 fun get_string(key: JavaString, def_value: JavaString): JavaString in "Java" `{
96 String return_value = null;
97 try {
98 return_value = recv.getString(key, def_value);
99 } catch (ClassCastException e) {
100 return def_value;
101 }
102
103 return return_value;
104 `}
105
106 # HACK for bug #845
107 redef fun new_global_ref import sys, Sys.jni_env `{
108 Sys sys = NativeSharedPreferences_sys(recv);
109 JNIEnv *env = Sys_jni_env(sys);
110 return (*env)->NewGlobalRef(env, recv);
111 `}
112 end
113
114 extern class NativeSharedPreferencesEditor in "Java" `{ android.content.SharedPreferences$Editor `}
115 super JavaObject
116 redef type SELF: NativeSharedPreferencesEditor
117
118 fun clear: NativeSharedPreferencesEditor in "Java" `{ return recv.clear(); `}
119 fun commit: Bool in "Java" `{ return recv.commit(); `}
120 fun put_boolean(key: JavaString, value: Bool ): NativeSharedPreferencesEditor in "Java" `{
121 return recv.putBoolean (key, value);
122 `}
123 fun put_float(key: JavaString, value: Float): NativeSharedPreferencesEditor in "Java" `{
124 return recv.putFloat(key, (float) value);
125 `}
126 fun put_int(key: JavaString, value: Int): NativeSharedPreferencesEditor in "Java" `{
127 return recv.putInt(key, (int)value);
128 `}
129 fun put_long(key: JavaString, value: Int): NativeSharedPreferencesEditor in "Java" `{
130 return recv.putLong(key, value);
131 `}
132 fun put_string(key: JavaString, value: JavaString): NativeSharedPreferencesEditor in "Java" `{
133 return recv.putString(key, value);
134 `}
135 fun remove(key: JavaString): NativeSharedPreferencesEditor in "Java" `{
136 return recv.remove(key);
137 `}
138
139 # HACK for bug #845
140 redef fun new_global_ref import sys, Sys.jni_env `{
141 Sys sys = NativeSharedPreferencesEditor_sys(recv);
142 JNIEnv *env = Sys_jni_env(sys);
143 return (*env)->NewGlobalRef(env, recv);
144 `}
145 end
146
147 # Provides services to save and load data for the android platform
148 class SharedPreferences
149 protected var context: NativeActivity
150 protected var shared_preferences: NativeSharedPreferences
151 protected var editor: NativeSharedPreferencesEditor
152
153 # Automatically commits every saving/removing instructions (`true` by default)
154 var auto_commit = true
155
156 protected init(app: App, file_name: String, mode: Int)
157 do
158 self.context = app.native_activity
159 sys.jni_env.push_local_frame(1)
160 setup(file_name.to_java_string, mode)
161 sys.jni_env.pop_local_frame
162 end
163
164 # Restricts file access to the current application
165 init privately(app: App, file_name: String)
166 do
167 self.init(app, file_name, private_mode)
168 end
169
170 # File access mode
171 private fun private_mode: Int in "Java" `{ return Context.MODE_PRIVATE; `}
172
173 private fun set_vars(shared_pref: NativeSharedPreferences, editor: NativeSharedPreferencesEditor)
174 do
175 self.shared_preferences = shared_pref.new_global_ref
176 self.editor = editor.new_global_ref
177 end
178
179 private fun setup(file_name: JavaString, mode: Int) import context, set_vars in "Java" `{
180 Activity context = (Activity) SharedPreferences_context(recv);
181 SharedPreferences sp;
182
183 // Uses default SharedPreferences if file_name is an empty String
184 if (file_name.equals("")) {
185 sp = context.getPreferences((int)mode);
186 } else {
187 sp = context.getSharedPreferences(file_name, (int)mode);
188 }
189
190 SharedPreferences.Editor editor = sp.edit();
191
192 SharedPreferences_set_vars(recv, sp, editor);
193 `}
194
195 private fun commit_if_auto do if auto_commit then self.commit
196
197 # Returns true if there's an entry corresponding the given key
198 fun has(key: String): Bool
199 do
200 sys.jni_env.push_local_frame(2)
201 var return_value = shared_preferences.contains(key.to_java_string)
202 sys.jni_env.pop_local_frame
203 return return_value
204 end
205
206 # Returns a `HashMap` containing all entries or `null` if there's no entries
207 #
208 # User has to manage local stack deallocation himself
209 #
210 # Example :
211 # ~~~
212 # var foo = new HashMap[JavaString, JavaObject]
213 # # ...
214 # for key, value in foo do
215 # key.delete_local_ref
216 # value.delete_local_ref
217 # end
218 # ~~~
219 # *You should use Nit getters instead and get each value one by one*
220 fun all: nullable HashMap[JavaString, JavaObject]
221 do
222 var hashmap = shared_preferences.get_all
223 if hashmap.is_empty then return null
224 return hashmap
225 end
226
227 # Returns the `Bool` value corresponding the given key or `def_value` if none
228 # or if the value isn't of correct type
229 fun bool(key: String, def_value: Bool): Bool
230 do
231 sys.jni_env.push_local_frame(2)
232 var return_value = shared_preferences.get_boolean(key.to_java_string, def_value)
233 sys.jni_env.pop_local_frame
234 return return_value
235 end
236
237 # Returns the `Float` value corresponding the given key or `def_value` if none
238 # or if the value isn't of correct type
239 fun float(key: String, def_value: Float): Float
240 do
241 sys.jni_env.push_local_frame(2)
242 var return_value = shared_preferences.get_float(key.to_java_string, def_value)
243 sys.jni_env.pop_local_frame
244 return return_value
245 end
246
247 # Returns the `Int` value corresponding the given key or `def_value` if none
248 # or if the value isn't of correct type
249 # Be aware of possible `def_value` integer overflow as the Nit `Int` corresponds
250 # to Java `long`
251 fun int(key: String, def_value: Int): Int
252 do
253 sys.jni_env.push_local_frame(2)
254 var return_value = shared_preferences.get_int(key.to_java_string, def_value)
255 sys.jni_env.pop_local_frame
256 return return_value
257 end
258
259 # Returns the `Int` value corresponding the given key or `def_value` if none
260 # or if the value isn't of correct type
261 # Calls `getLong(key, value)` java method
262 # Nit `Int` is equivalent to Java `long` so that no integer overflow will occur
263 fun long(key: String, def_value: Int): Int
264 do
265 sys.jni_env.push_local_frame(2)
266 var return_value = shared_preferences.get_long(key.to_java_string, def_value)
267 sys.jni_env.pop_local_frame
268 return return_value
269 end
270
271 # Returns the `String` value corresponding the given key or `def_value` if none
272 # or if the value isn't of correct type
273 fun string(key: String, def_value: String): String
274 do
275 sys.jni_env.push_local_frame(3)
276 var java_return_value = shared_preferences.get_string(key.to_java_string,
277 def_value.to_java_string)
278 var nit_return_value = java_return_value.to_s
279 sys.jni_env.pop_local_frame
280 return nit_return_value
281 end
282
283 # Clears all the dictionnary entries in the specified file or the default file
284 # if none specified at instanciation
285 # Returns `self` allowing fluent programming
286 fun clear: SharedPreferences
287 do
288 editor.clear
289 commit_if_auto
290 return self
291 end
292
293 # If auto_commit is `false`, has to be called to save the data to persistant memory
294 fun commit: Bool
295 do
296 sys.jni_env.push_local_frame(1)
297 var return_value = editor.commit
298 sys.jni_env.pop_local_frame
299 return return_value
300 end
301
302 # Set a key-value pair using a `Bool` value
303 # Returns `self` allowing fluent programming
304 fun add_bool(key: String, value: Bool ): SharedPreferences
305 do
306 sys.jni_env.push_local_frame(1)
307 editor.put_boolean(key.to_java_string, value)
308 sys.jni_env.pop_local_frame
309 commit_if_auto
310 return self
311 end
312
313 # Set a key-value pair using a `Float` value
314 # Returns `self` allowing fluent programming
315 #
316 # Be aware of possible loss of precision as Nit `Float` corresponds to Java `double`
317 # and the methods stores a Java `float`
318 fun add_float(key: String, value: Float): SharedPreferences
319 do
320 sys.jni_env.push_local_frame(1)
321 editor.put_float(key.to_java_string, value)
322 sys.jni_env.pop_local_frame
323 commit_if_auto
324 return self
325 end
326
327 # Set a key-value pair using a `Int` type value
328 # Returns `self` allowing fluent programming
329 #
330 # Be aware of possible integer overflow as the Nit `Int` corresponds to Java `long`
331 # and the methods stores a Java `int`
332 # *You might want to use add_long instead*
333 fun add_int(key: String, value: Int): SharedPreferences
334 do
335 sys.jni_env.push_local_frame(1)
336 editor.put_int(key.to_java_string, value)
337 sys.jni_env.pop_local_frame
338 commit_if_auto
339 return self
340 end
341
342 # Set a key-value pair using a `Int` type value
343 # Returns `self` allowing fluent programming
344 fun add_long(key: String, value: Int): SharedPreferences
345 do
346 sys.jni_env.push_local_frame(1)
347 editor.put_long(key.to_java_string, value)
348 sys.jni_env.pop_local_frame
349 commit_if_auto
350 return self
351 end
352
353 # Set a key-value pair using a `String` type value
354 # Returns `self` allowing fluent programming
355 fun add_string(key: String, value: String): SharedPreferences
356 do
357 sys.jni_env.push_local_frame(2)
358 editor.put_string(key.to_java_string, value.to_java_string)
359 sys.jni_env.pop_local_frame
360 commit_if_auto
361 return self
362 end
363
364 # Removes the corresponding entry in the file
365 # Returns `self` allowing fluent programming
366 fun remove(key: String): SharedPreferences
367 do
368 sys.jni_env.push_local_frame(1)
369 editor.remove(key.to_java_string)
370 sys.jni_env.pop_local_frame
371 commit_if_auto
372 return self
373 end
374
375 # Deallocate global references allocated by the SharedPreferences instance
376 fun destroy
377 do
378 self.shared_preferences.delete_global_ref
379 self.editor.delete_global_ref
380 end
381
382 # Store `value` as a serialized Json string
383 fun []=(key: String, value: nullable Serializable)
384 do
385 var serialized_string = new StringOStream
386 var serializer = new JsonSerializer(serialized_string)
387 serializer.serialize(value)
388
389 add_string(key, serialized_string.to_s)
390 commit_if_auto
391 end
392
393 # Retrieve an `Object` stored via `[]=` function
394 #
395 # Returns `null` if there's no serialized object corresponding to the given key
396 # Make sure that the serialized object is `auto_serializable` or that it redefines
397 # the appropriate methods. Refer to `Serializable` documentation for further details
398 fun [](key: String): nullable Object
399 do
400 var serialized_string = self.string(key, "")
401
402 if serialized_string == "" then return null
403
404 var deserializer = new JsonDeserializer(serialized_string)
405 return deserializer.deserialize
406 end
407 end
408
409 redef class App
410 fun shared_preferences: SharedPreferences is cached do
411 return new SharedPreferences.privately(self, "")
412 end
413 end