summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuilherme Lepsch <lepsch@expertisesolutions.com.br>2015-02-26 17:02:42 -0300
committerGuilherme Lepsch <lepsch@expertisesolutions.com.br>2015-02-27 12:10:34 -0300
commit8fef814be8fb8bbcdd098218db4c518e20056ce2 (patch)
treed56ee079955d304e0d4a59f6c76605a20637b426
parent2a731b78cba1597a3d6489cea2afb11207a331ba (diff)
ejson: Get/Set properties, child_add/del
-rw-r--r--src/lib/Ejson.h15
-rw-r--r--src/lib/ejson_model.c917
-rw-r--r--src/lib/ejson_model.eo8
-rw-r--r--src/lib/ejson_model_private.h11
-rw-r--r--src/tests/Makefile.am10
-rw-r--r--src/tests/ejson_suite.c2
-rw-r--r--src/tests/ejson_test_ejson_model.c724
7 files changed, 1598 insertions, 89 deletions
diff --git a/src/lib/Ejson.h b/src/lib/Ejson.h
index 7d2e82c..d6cdefe 100644
--- a/src/lib/Ejson.h
+++ b/src/lib/Ejson.h
@@ -2,11 +2,26 @@
2#define EJSON_H 2#define EJSON_H
3 3
4#include <Ecore.h> 4#include <Ecore.h>
5#include <Emodel.h>
5 6
6#ifdef __cplusplus 7#ifdef __cplusplus
7extern "C" { 8extern "C" {
8#endif 9#endif
9 10
11typedef enum {
12 EJSON_MODEL_TYPE_NULL,
13 EJSON_MODEL_TYPE_BOOLEAN,
14 EJSON_MODEL_TYPE_DOUBLE,
15 EJSON_MODEL_TYPE_INT,
16 EJSON_MODEL_TYPE_STRING,
17 EJSON_MODEL_TYPE_OBJECT,
18 EJSON_MODEL_TYPE_ARRAY
19} Ejson_Model_Type;
20
21#define EJSON_MODEL_NAME_PROPERTY "name"
22#define EJSON_MODEL_VALUE_PROPERTY "value"
23#define EJSON_MODEL_JSON_PROPERTY "json"
24
10/** 25/**
11 * @brief Initialize ejson. 26 * @brief Initialize ejson.
12 * 27 *
diff --git a/src/lib/ejson_model.c b/src/lib/ejson_model.c
index 51400bc..57786ca 100644
--- a/src/lib/ejson_model.c
+++ b/src/lib/ejson_model.c
@@ -4,14 +4,40 @@
4 4
5#include "ejson_model_private.h" 5#include "ejson_model_private.h"
6 6
7#include <stdint.h>
8#include <stdlib.h>
9
7#define MY_CLASS EJSON_MODEL_CLASS 10#define MY_CLASS EJSON_MODEL_CLASS
8#define MY_CLASS_NAME "Ejson_Model" 11#define MY_CLASS_NAME "Ejson_Model"
9 12
10static void _ejson_model_emodel_properties_load(Eo *, Ejson_Model_Data *); 13typedef struct _Ejson_Model_Child_Data
11static void _ejson_model_emodel_children_load(Eo *, Ejson_Model_Data *); 14{
12static void _ejson_model_init(Ejson_Model_Data *); 15 Eina_Stringshare *name;
13static void _ejson_model_shutdown(Ejson_Model_Data *); 16 int index;
17} Ejson_Model_Child_Data;
18
19static void _ejson_model_properties_load(Ejson_Model_Data *);
20static void _ejson_model_children_load(Ejson_Model_Data *);
21static bool _ejson_model_init(Ejson_Model_Data *);
14static void _ejson_model_clear(Ejson_Model_Data *); 22static void _ejson_model_clear(Ejson_Model_Data *);
23static void _ejson_model_properties_setup(Ejson_Model_Data *);
24static void _ejson_model_properties_setup_cb(void *, int, Eina_Value_Struct_Member *);
25static Ejson_Model_Type _ejson_model_parent_type_get(Ejson_Model_Data *);
26static void _ejson_model_children_hash_free(void *);
27static bool _ejson_model_name_property_set(Ejson_Model_Data *, Eina_Value *);
28static bool _ejson_model_value_property_set(Ejson_Model_Data *, Eina_Value *);
29static bool _ejson_model_json_property_set(Ejson_Model_Data *, Eina_Value *);
30static void _ejson_model_invalidate(Ejson_Model_Data *);
31static bool _ejson_model_stream_load(Ejson_Model_Data *);
32static Eina_Bool _ejson_model_eina_value_as(Eina_Value *, const Eina_Value_Type *, void *);
33static Ejson_Model_Type _ejson_model_type_from_json_object(json_object *json);
34static bool _ejson_model_object_child_add(Ejson_Model_Data *, Ejson_Model_Data *, const char *);
35static bool _ejson_model_array_child_add(Ejson_Model_Data *, Ejson_Model_Data *, int);
36static bool _ejson_model_child_add(Ejson_Model_Data *, Ejson_Model_Data *, Ejson_Model_Child_Data *);
37static Ejson_Model_Child_Data *_ejson_model_object_child_data_new(const char *);
38static Ejson_Model_Child_Data *_ejson_model_array_child_data_new(int*);
39typedef Ejson_Model_Child_Data *(*Ejson_Model_Child_Data_New)(void *);
40static void _ejson_model_child_new(Ejson_Model_Data *, json_object *, void *, Ejson_Model_Child_Data_New);
15 41
16static void 42static void
17_ejson_model_eo_base_constructor(Eo *obj, Ejson_Model_Data *pd) 43_ejson_model_eo_base_constructor(Eo *obj, Ejson_Model_Data *pd)
@@ -23,18 +49,24 @@ _ejson_model_eo_base_constructor(Eo *obj, Ejson_Model_Data *pd)
23 pd->load.status = EMODEL_LOAD_STATUS_UNLOADED; 49 pd->load.status = EMODEL_LOAD_STATUS_UNLOADED;
24 pd->json = NULL; 50 pd->json = NULL;
25 pd->properties_array = NULL; 51 pd->properties_array = NULL;
52 pd->properties_desc = NULL;
53 pd->properties = NULL;
26 pd->children_list = NULL; 54 pd->children_list = NULL;
27 pd->filename = NULL; 55 pd->children_hash = eina_hash_pointer_new(_ejson_model_children_hash_free);
56 pd->stream = NULL;
57 pd->type = EJSON_MODEL_TYPE_NULL;
58 pd->properties_calc = eina_array_new(1);
59 eina_array_push(pd->properties_calc, EJSON_MODEL_JSON_PROPERTY);
60 pd->json_property_valid = false;
28} 61}
29 62
30static void 63static void
31_ejson_model_constructor(Eo *obj EINA_UNUSED, 64_ejson_model_constructor(Eo *obj EINA_UNUSED,
32 Ejson_Model_Data *pd, 65 Ejson_Model_Data *pd,
33 const char* filename) 66 Ejson_Model_Type type)
34{ 67{
35 DBG("(%p)", obj); 68 DBG("(%p)", obj);
36 69 pd->type = type;
37 pd->filename = eina_stringshare_add(filename);
38} 70}
39 71
40static void 72static void
@@ -42,10 +74,12 @@ _ejson_model_eo_base_destructor(Eo *obj, Ejson_Model_Data *pd)
42{ 74{
43 DBG("(%p)", obj); 75 DBG("(%p)", obj);
44 76
45 eina_stringshare_del(pd->filename);
46
47 _ejson_model_clear(pd); 77 _ejson_model_clear(pd);
48 78
79 eina_hash_free(pd->children_hash);
80 emodel_value_struct_desc_free(pd->properties_desc);
81 eina_array_free(pd->properties_calc);
82
49 eo_do_super(obj, MY_CLASS, eo_destructor()); 83 eo_do_super(obj, MY_CLASS, eo_destructor());
50} 84}
51 85
@@ -58,14 +92,6 @@ _ejson_model_emodel_properties_list_get(Eo *obj EINA_UNUSED,
58 EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EMODEL_LOAD_STATUS_ERROR); 92 EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EMODEL_LOAD_STATUS_ERROR);
59 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, EMODEL_LOAD_STATUS_ERROR); 93 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, EMODEL_LOAD_STATUS_ERROR);
60 94
61 if (NULL == pd->properties_array)
62 {
63 pd->properties_array = eina_array_new(1);
64 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->properties_array, EMODEL_LOAD_STATUS_ERROR);
65
66 // TODO: Populate properties list
67 }
68
69 *(Eina_Array**)properties_array = pd->properties_array; 95 *(Eina_Array**)properties_array = pd->properties_array;
70 return pd->load.status; 96 return pd->load.status;
71} 97}
@@ -78,23 +104,265 @@ _ejson_model_emodel_properties_load(Eo *obj, Ejson_Model_Data *pd)
78 if (pd->load.status & EMODEL_LOAD_STATUS_LOADED_PROPERTIES) 104 if (pd->load.status & EMODEL_LOAD_STATUS_LOADED_PROPERTIES)
79 return; 105 return;
80 106
81 if (!pd->json) 107 if (!_ejson_model_init(pd))
82 _ejson_model_init(pd); 108 return;
109
110 emodel_load_set(pd->obj, &pd->load, EMODEL_LOAD_STATUS_LOADING_PROPERTIES);
83 111
84 // TODO: Load properties 112 _ejson_model_properties_load(pd);
85 113
86 emodel_load_set(pd->obj, &pd->load, EMODEL_LOAD_STATUS_LOADED_PROPERTIES); 114 emodel_load_set(pd->obj, &pd->load, EMODEL_LOAD_STATUS_LOADED_PROPERTIES);
87} 115}
88 116
117static void
118_ejson_model_properties_load(Ejson_Model_Data *pd)
119{
120 _ejson_model_properties_setup(pd);
121 if (!pd->json)
122 return;
123
124 Eina_Value *value = NULL;
125 switch (pd->type)
126 {
127 case EJSON_MODEL_TYPE_NULL:
128 break;
129 case EJSON_MODEL_TYPE_BOOLEAN:
130 {
131 json_bool v = json_object_get_boolean(pd->json);
132 value = eina_value_new(EINA_VALUE_TYPE_INT);
133 eina_value_set(value, v);
134 break;
135 }
136 case EJSON_MODEL_TYPE_DOUBLE:
137 {
138 double v = json_object_get_boolean(pd->json);
139 value = eina_value_new(EINA_VALUE_TYPE_DOUBLE);
140 eina_value_set(value, v);
141 break;
142 }
143 case EJSON_MODEL_TYPE_INT:
144 {
145 int64_t v = json_object_get_int64(pd->json);
146 value = eina_value_new(EINA_VALUE_TYPE_INT64);
147 eina_value_set(value, v);
148 break;
149 }
150 case EJSON_MODEL_TYPE_STRING:
151 {
152 const char *v = json_object_get_string(pd->json);
153 value = eina_value_new(EINA_VALUE_TYPE_STRING);
154 eina_value_set(value, v);
155 break;
156 }
157 case EJSON_MODEL_TYPE_OBJECT:
158 break;
159 case EJSON_MODEL_TYPE_ARRAY:
160 break;
161 }
162
163 if (value)
164 {
165 Eina_Bool ret = eina_value_struct_value_set(pd->properties,
166 EJSON_MODEL_VALUE_PROPERTY,
167 value);
168 eina_value_free(value);
169 EINA_SAFETY_ON_FALSE_RETURN(ret);
170 }
171
172 if (EJSON_MODEL_TYPE_OBJECT == _ejson_model_parent_type_get(pd))
173 {
174 Eo *parent = eo_do(pd->obj, eo_parent_get());
175
176 Ejson_Model_Data *parent_pd = eo_data_scope_get(parent, EJSON_MODEL_CLASS);
177 EINA_SAFETY_ON_NULL_RETURN(parent_pd);
178
179 Ejson_Model_Child_Data *child_data = eina_hash_find(parent_pd->children_hash, &pd->obj);
180 EINA_SAFETY_ON_NULL_RETURN(child_data);
181
182 Eina_Bool ret = eina_value_struct_set(pd->properties,
183 EJSON_MODEL_NAME_PROPERTY,
184 child_data->name);
185 EINA_SAFETY_ON_FALSE_RETURN(ret);
186 }
187
188 Emodel_Property_Event evt = {.changed_properties = pd->properties,
189 .invalidated_properties = pd->properties_calc};
190 eo_do(pd->obj, eo_event_callback_call(EMODEL_EVENT_PROPERTIES_CHANGED, &evt));
191}
192
89static Emodel_Load_Status 193static Emodel_Load_Status
90_ejson_model_emodel_property_set(Eo *obj EINA_UNUSED, 194_ejson_model_emodel_property_set(Eo *obj,
91 Ejson_Model_Data *pd EINA_UNUSED, 195 Ejson_Model_Data *pd,
92 const char *property EINA_UNUSED, 196 const char *property,
93 Eina_Value value EINA_UNUSED) 197 Eina_Value value)
94{ 198{
95 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EMODEL_LOAD_STATUS_ERROR); 199 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EMODEL_LOAD_STATUS_ERROR);
96 DBG("(%p): property=%s", obj, property); 200 DBG("(%p): property=%s", obj, property);
97 return EMODEL_LOAD_STATUS_ERROR; 201
202 const bool is_json_property = strcmp(EJSON_MODEL_JSON_PROPERTY, property) == 0;
203 if (is_json_property)
204 {
205 if (!_ejson_model_json_property_set(pd, &value))
206 return EMODEL_LOAD_STATUS_ERROR;
207
208 if (!(pd->load.status & EMODEL_LOAD_STATUS_LOADED))
209 return pd->load.status;
210 }
211 else
212 {
213 if (!(pd->load.status & EMODEL_LOAD_STATUS_LOADED_PROPERTIES))
214 return EMODEL_LOAD_STATUS_ERROR;
215
216 const bool is_name_property = strcmp(EJSON_MODEL_NAME_PROPERTY, property) == 0;
217 const bool is_value_property = strcmp(EJSON_MODEL_VALUE_PROPERTY, property) == 0;
218
219 if (!is_name_property && !is_value_property)
220 {
221 ERR("Unrecognized property: %s", property);
222 return EMODEL_LOAD_STATUS_ERROR;
223 }
224
225 if (is_name_property)
226 {
227 if (!_ejson_model_name_property_set(pd, &value))
228 return EMODEL_LOAD_STATUS_ERROR;
229 }
230 else if (is_value_property)
231 {
232 if (!_ejson_model_value_property_set(pd, &value))
233 return EMODEL_LOAD_STATUS_ERROR;
234 }
235 }
236
237 pd->json_property_valid = false;
238 Emodel_Property_Event evt = {.changed_properties = pd->properties,
239 .invalidated_properties = pd->properties_calc};
240 eo_do(pd->obj, eo_event_callback_call(EMODEL_EVENT_PROPERTIES_CHANGED, &evt));
241
242 return pd->load.status;
243}
244
245static bool
246_ejson_model_name_property_set(Ejson_Model_Data *pd, Eina_Value *value)
247{
248 DBG("(%p)", pd->obj);
249 Ejson_Model_Type parent_type = _ejson_model_parent_type_get(pd);
250 if (EJSON_MODEL_TYPE_OBJECT != parent_type)
251 {
252 ERR("Only object types have the '" EJSON_MODEL_NAME_PROPERTY "' property");
253 return false;
254 }
255
256 Eina_Bool ret = eina_value_struct_value_set(pd->properties, EJSON_MODEL_NAME_PROPERTY, value);
257 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, false);
258
259 return true;
260}
261
262static bool
263_ejson_model_value_property_set(Ejson_Model_Data *pd, Eina_Value *value)
264{
265 DBG("(%p)", pd->obj);
266 const Eina_Value_Type * const value_type = eina_value_type_get(value);
267 EINA_SAFETY_ON_NULL_RETURN_VAL(value_type, false);
268
269 json_object *json = NULL;
270 switch (pd->type)
271 {
272 case EJSON_MODEL_TYPE_BOOLEAN:
273 {
274 int v;
275 Eina_Bool ret = _ejson_model_eina_value_as(value, EINA_VALUE_TYPE_INT, &v);
276 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, false);
277
278 json = json_object_new_boolean(v ? TRUE : FALSE);
279 break;
280 }
281 case EJSON_MODEL_TYPE_DOUBLE:
282 {
283 double v;
284 Eina_Bool ret = _ejson_model_eina_value_as(value, EINA_VALUE_TYPE_DOUBLE, &v);
285 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, false);
286
287 json = json_object_new_double(v);
288 break;
289 }
290 case EJSON_MODEL_TYPE_INT:
291 {
292 int64_t v;
293 Eina_Bool ret = _ejson_model_eina_value_as(value, EINA_VALUE_TYPE_INT64, &v);
294 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, false);
295
296 json = json_object_new_int64(v);
297 break;
298 }
299 case EJSON_MODEL_TYPE_STRING:
300 {
301 const char *v;
302 Eina_Bool ret = _ejson_model_eina_value_as(value, EINA_VALUE_TYPE_STRING, &v);
303 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, false);
304
305 json = json_object_new_string(v);
306 break;
307 }
308 case EJSON_MODEL_TYPE_NULL:
309 return false;
310 case EJSON_MODEL_TYPE_OBJECT:
311 return false;
312 case EJSON_MODEL_TYPE_ARRAY:
313 return false;
314 }
315
316 Eina_Bool ret = eina_value_struct_value_set(pd->properties, EJSON_MODEL_VALUE_PROPERTY, value);
317 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
318
319 json_object_put(pd->json);
320 pd->json = json;
321
322 return true;
323
324on_error:
325 json_object_put(json);
326 return false;
327}
328
329static bool
330_ejson_model_json_property_set(Ejson_Model_Data *pd, Eina_Value *value)
331{
332 DBG("(%p)", pd->obj);
333 char *stream = eina_value_to_string(value);
334 EINA_SAFETY_ON_NULL_RETURN_VAL(stream, false);
335
336 Emodel_Load_Status old_status = pd->load.status;
337 switch (old_status & EMODEL_LOAD_STATUS_LOADED)
338 {
339 case EMODEL_LOAD_STATUS_LOADED_PROPERTIES:
340 emodel_load_set(pd->obj, &pd->load, EMODEL_LOAD_STATUS_LOADING_PROPERTIES);
341 break;
342 case EMODEL_LOAD_STATUS_LOADED_CHILDREN:
343 emodel_load_set(pd->obj, &pd->load, EMODEL_LOAD_STATUS_LOADING_CHILDREN);
344 break;
345 case EMODEL_LOAD_STATUS_LOADED:
346 emodel_load_set(pd->obj, &pd->load, EMODEL_LOAD_STATUS_LOADING);
347 break;
348 default: break;
349 }
350
351 _ejson_model_clear(pd);
352 emodel_value_struct_desc_free(pd->properties_desc);
353
354 pd->stream = stream;
355
356 _ejson_model_stream_load(pd);
357
358 if (old_status & EMODEL_LOAD_STATUS_LOADED_PROPERTIES)
359 _ejson_model_properties_load(pd);
360
361 if (old_status & EMODEL_LOAD_STATUS_LOADED_CHILDREN)
362 _ejson_model_children_load(pd);
363
364 emodel_load_set(pd->obj, &pd->load, old_status);
365 return true;
98} 366}
99 367
100static Emodel_Load_Status 368static Emodel_Load_Status
@@ -110,9 +378,28 @@ _ejson_model_emodel_property_get(Eo *obj EINA_UNUSED,
110 if (!(pd->load.status & EMODEL_LOAD_STATUS_LOADED_PROPERTIES)) 378 if (!(pd->load.status & EMODEL_LOAD_STATUS_LOADED_PROPERTIES))
111 return EMODEL_LOAD_STATUS_ERROR; 379 return EMODEL_LOAD_STATUS_ERROR;
112 380
113 // TODO: Get property 381 if (strcmp(EJSON_MODEL_NAME_PROPERTY, property) == 0 ||
382 strcmp(EJSON_MODEL_VALUE_PROPERTY, property) == 0)
383 {
384 if (!eina_value_struct_value_get(pd->properties, property, value))
385 return EMODEL_LOAD_STATUS_ERROR;
386 return pd->load.status;
387 }
388
389 if (strcmp(EJSON_MODEL_JSON_PROPERTY, property) == 0)
390 {
391 if (!pd->json_property_valid)
392 {
393 const char *json = json_object_to_json_string(pd->json);
394 pd->json_property_valid = eina_value_struct_set(pd->properties, property, json) == EINA_TRUE;
395 }
114 396
115 return pd->load.status; 397 if (!pd->json_property_valid || !eina_value_struct_value_get(pd->properties, property, value))
398 return EMODEL_LOAD_STATUS_ERROR;
399 return pd->load.status;
400 }
401
402 return EMODEL_LOAD_STATUS_ERROR;
116} 403}
117 404
118static void 405static void
@@ -120,11 +407,25 @@ _ejson_model_emodel_load(Eo *obj EINA_UNUSED, Ejson_Model_Data *pd)
120{ 407{
121 DBG("(%p)", obj); 408 DBG("(%p)", obj);
122 409
123 if (!pd->json) 410 if ((pd->load.status & EMODEL_LOAD_STATUS_LOADED) == EMODEL_LOAD_STATUS_LOADED)
124 _ejson_model_init(pd); 411 return;
125 412
126 _ejson_model_emodel_properties_load(obj, pd); 413 if (!_ejson_model_init(pd))
127 _ejson_model_emodel_children_load(obj, pd); 414 return;
415
416 if (!(pd->load.status & EMODEL_LOAD_STATUS_LOADED_PROPERTIES))
417 {
418 emodel_load_set(pd->obj, &pd->load, EMODEL_LOAD_STATUS_LOADING_PROPERTIES);
419 _ejson_model_properties_load(pd);
420 }
421
422 if (!(pd->load.status & EMODEL_LOAD_STATUS_LOADED_CHILDREN))
423 {
424 emodel_load_set(pd->obj, &pd->load, EMODEL_LOAD_STATUS_LOADING_CHILDREN);
425 _ejson_model_children_load(pd);
426 }
427
428 emodel_load_set(pd->obj, &pd->load, EMODEL_LOAD_STATUS_LOADED);
128} 429}
129 430
130static Emodel_Load_Status 431static Emodel_Load_Status
@@ -144,20 +445,207 @@ _ejson_model_emodel_unload(Eo *obj EINA_UNUSED, Ejson_Model_Data *pd)
144 emodel_load_set(pd->obj, &pd->load, EMODEL_LOAD_STATUS_UNLOADED); 445 emodel_load_set(pd->obj, &pd->load, EMODEL_LOAD_STATUS_UNLOADED);
145} 446}
146 447
448static Eina_Bool
449_ejson_model_child_properties_changed_cb(void *data,
450 Eo *child,
451 const Eo_Event_Description *desc EINA_UNUSED,
452 void *event_info)
453{
454 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EO_CALLBACK_STOP);
455 EINA_SAFETY_ON_NULL_RETURN_VAL(event_info, EO_CALLBACK_STOP);
456 Ejson_Model_Data *pd = (Ejson_Model_Data*)data;
457 DBG("(%p)", pd->obj);
458 //eo_do(child, eo_event_callback_del(EMODEL_EVENT_PROPERTIES_CHANGED, _ejson_model_child_properties_changed_cb, pd));
459
460 // Only user changes count
461 Emodel_Load_Status child_status = eo_do(child, emodel_load_status_get());
462 if (!(child_status & EMODEL_LOAD_STATUS_LOADED_PROPERTIES))
463 return EO_CALLBACK_CONTINUE;
464
465 Ejson_Model_Data *child_pd = eo_data_scope_get(child, EJSON_MODEL_CLASS);
466 EINA_SAFETY_ON_NULL_RETURN_VAL(child_pd, EO_CALLBACK_STOP);
467
468 const char *current_name = NULL;
469 if (EJSON_MODEL_TYPE_OBJECT == pd->type)
470 {
471 Eina_Bool ret = eina_value_struct_get(child_pd->properties,
472 EJSON_MODEL_NAME_PROPERTY,
473 &current_name);
474 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EO_CALLBACK_STOP);
475
476 // Continue only if the name is already assigned
477 if (!current_name || !strlen(current_name))
478 return EO_CALLBACK_CONTINUE;
479 }
480
481 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->children_hash, EO_CALLBACK_STOP);
482 Ejson_Model_Child_Data *child_data = eina_hash_find(pd->children_hash, &child);
483 if (child_data)
484 {
485 DBG("(%p) Setting child %p value", pd->obj, child_pd->obj);
486 switch (pd->type)
487 {
488 case EJSON_MODEL_TYPE_OBJECT:
489 {
490 const bool is_name_changed = strcmp(current_name, child_data->name) == 0;
491 if (!is_name_changed)
492 {
493 json_object_object_del(pd->json, child_data->name);
494 eina_stringshare_del(child_data->name);
495 child_data->name = eina_stringshare_add(current_name);
496 }
497
498 json_object_object_add(pd->json, child_data->name, json_object_get(child_pd->json));
499 break;
500 }
501 case EJSON_MODEL_TYPE_ARRAY:
502 json_object_array_put_idx(pd->json, child_data->index, json_object_get(child_pd->json));
503 break;
504 default:
505 ERR("Type cannot have children: %d", pd->type);
506 return EO_CALLBACK_STOP;
507 }
508 }
509 else
510 {
511
512 bool ok = false;
513 switch (pd->type)
514 {
515 case EJSON_MODEL_TYPE_OBJECT:
516 json_object_object_add(pd->json, current_name, json_object_get(child_pd->json));
517 ok = _ejson_model_object_child_add(pd, child_pd, current_name);
518 break;
519 case EJSON_MODEL_TYPE_ARRAY:
520 {
521 int index = json_object_array_add(pd->json, json_object_get(child_pd->json));
522 ok = _ejson_model_array_child_add(pd, child_pd, index);
523 break;
524 }
525 default:
526 ERR("Current type cannot have children: %d", pd->type);
527 }
528
529 EINA_SAFETY_ON_FALSE_RETURN_VAL(ok, EO_CALLBACK_STOP);
530
531 unsigned int count = eina_list_count(pd->children_list);
532 Emodel_Children_Event evt = {.child = child, .index = count};
533 eo_do(pd->obj, eo_event_callback_call(EMODEL_EVENT_CHILD_ADDED, &evt),
534 eo_event_callback_call(EMODEL_EVENT_CHILDREN_COUNT_CHANGED, &count));
535 }
536
537 _ejson_model_invalidate(pd);
538
539 Emodel_Property_Event evt = {.invalidated_properties = pd->properties_calc};
540 eo_do(pd->obj, eo_event_callback_call(EMODEL_EVENT_PROPERTIES_CHANGED, &evt));
541
542 return EO_CALLBACK_CONTINUE;
543}
544
147Eo * 545Eo *
148_ejson_model_emodel_child_add(Eo *obj EINA_UNUSED, Ejson_Model_Data *pd EINA_UNUSED) 546_ejson_model_emodel_child_add(Eo *obj, Ejson_Model_Data *pd)
149{ 547{
150 DBG("(%p)", obj); 548 DBG("(%p)", obj);
151 return NULL; 549
550 if (!(pd->load.status & EMODEL_LOAD_STATUS_LOADED_CHILDREN))
551 return NULL;
552
553 json_type type = json_object_get_type(pd->json);
554 switch (type)
555 {
556 case json_type_array:
557 case json_type_object:
558 break;
559 default:
560 ERR("Value types cannot have children: %d", type);
561 return NULL;
562 }
563
564 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->json, NULL);
565
566 Eo *child = eo_add(EJSON_MODEL_CLASS,
567 obj,
568 ejson_model_constructor(EJSON_MODEL_TYPE_NULL));
569 eo_do(child, eo_event_callback_add(EMODEL_EVENT_PROPERTIES_CHANGED,
570 _ejson_model_child_properties_changed_cb,
571 pd));
572 return child;
152} 573}
153 574
154static Emodel_Load_Status 575static Emodel_Load_Status
155_ejson_model_emodel_child_del(Eo *obj EINA_UNUSED, 576_ejson_model_emodel_child_del(Eo *obj,
156 Ejson_Model_Data *pd EINA_UNUSED, 577 Ejson_Model_Data *pd,
157 Eo *child EINA_UNUSED) 578 Eo *child)
158{ 579{
159 DBG("(%p)", obj); 580 DBG("(%p)", obj);
160 return EMODEL_LOAD_STATUS_ERROR; 581 EINA_SAFETY_ON_NULL_RETURN_VAL(child, EMODEL_LOAD_STATUS_ERROR);
582
583 if (!(pd->load.status & EMODEL_LOAD_STATUS_LOADED_CHILDREN))
584 return EMODEL_LOAD_STATUS_ERROR;
585
586 Ejson_Model_Child_Data *child_data = eina_hash_find(pd->children_hash, &child);
587 if (!child_data)
588 {
589 ERR("Child not found: %p", child);
590 return EMODEL_LOAD_STATUS_ERROR;
591 }
592
593 switch (pd->type)
594 {
595 case EJSON_MODEL_TYPE_OBJECT:
596 {
597 json_object_object_del(pd->json, child_data->name);
598 break;
599 }
600 case EJSON_MODEL_TYPE_ARRAY:
601 {
602 int index = child_data->index;
603 json_object *json = json_object_new_array();
604
605 int length = json_object_array_length(pd->json);
606
607 for (int i = 0; i < index; ++i)
608 {
609 json_object *item = json_object_array_get_idx(pd->json, i);
610 json_object_array_add(json, json_object_get(item));
611 }
612
613 for (int i = index + 1; i < length; ++i)
614 {
615 json_object *item = json_object_array_get_idx(pd->json, i);
616 json_object_array_add(json, json_object_get(item));
617 }
618
619 Ejson_Model_Child_Data *data;
620 Eina_Iterator *it = eina_hash_iterator_data_new(pd->children_hash);
621 EINA_ITERATOR_FOREACH(it, data)
622 {
623 if (data->index > index)
624 --data->index;
625 }
626
627 json_object_put(pd->json);
628 pd->json = json;
629 break;
630 }
631 default: return EMODEL_LOAD_STATUS_ERROR;
632 }
633
634 pd->children_list = eina_list_remove(pd->children_list, child);
635 Eina_Bool ret = eina_hash_del(pd->children_hash, &child, NULL);
636 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EMODEL_LOAD_STATUS_ERROR);
637 eo_del(child);
638
639 pd->json_property_valid = false;
640 unsigned int count = eina_list_count(pd->children_list);
641 Emodel_Property_Event prop_event = {.changed_properties = pd->properties,
642 .invalidated_properties = pd->properties_calc};
643 Emodel_Children_Event added_event = {.child = child, .index = count};
644 eo_do(obj, eo_event_callback_call(EMODEL_EVENT_PROPERTIES_CHANGED, &prop_event),
645 eo_event_callback_call(EMODEL_EVENT_CHILD_ADDED, &added_event),
646 eo_event_callback_call(EMODEL_EVENT_CHILDREN_COUNT_CHANGED, &count));
647
648 return pd->load.status;
161} 649}
162 650
163static Emodel_Load_Status 651static Emodel_Load_Status
@@ -198,59 +686,130 @@ _ejson_model_emodel_children_load(Eo *obj EINA_UNUSED, Ejson_Model_Data *pd)
198 if (pd->load.status & EMODEL_LOAD_STATUS_LOADED_CHILDREN) 686 if (pd->load.status & EMODEL_LOAD_STATUS_LOADED_CHILDREN)
199 return; 687 return;
200 688
201 if (!pd->json) 689 if (!_ejson_model_init(pd))
202 _ejson_model_init(pd); 690 return;
203
204 // TODO: ...
205 691
206 emodel_load_set(pd->obj, &pd->load, EMODEL_LOAD_STATUS_LOADING_CHILDREN); 692 emodel_load_set(pd->obj, &pd->load, EMODEL_LOAD_STATUS_LOADING_CHILDREN);
207}
208 693
209static const char * 694 _ejson_model_children_load(pd);
210_ejson_model_filename_get(Eo *obj EINA_UNUSED, Ejson_Model_Data *pd) 695
211{ 696 emodel_load_set(pd->obj, &pd->load, EMODEL_LOAD_STATUS_LOADED_CHILDREN);
212 return pd->filename;
213} 697}
214 698
215static void 699static void
216_ejson_model_filename_set(Eo *obj EINA_UNUSED, Ejson_Model_Data *pd, const char *value) 700_ejson_model_children_load(Ejson_Model_Data *pd)
217{ 701{
218 eina_stringshare_del(pd->filename); 702 DBG("(%p)", pd->obj);
219 pd->filename = eina_stringshare_add(value); 703 if (!pd->json)
704 return;
705
706 switch (pd->type)
707 {
708 case EJSON_MODEL_TYPE_OBJECT:
709 {
710 Ejson_Model_Child_Data_New cb = (Ejson_Model_Child_Data_New)_ejson_model_object_child_data_new;
711 json_object_object_foreach(pd->json, name, json)
712 _ejson_model_child_new(pd, json, name, cb);
713 break;
714 }
715 case EJSON_MODEL_TYPE_ARRAY:
716 {
717 Ejson_Model_Child_Data_New cb = (Ejson_Model_Child_Data_New)_ejson_model_array_child_data_new;
718 int length = json_object_array_length(pd->json);
719 for (int i = 0; i < length; ++i)
720 {
721 json_object *json = json_object_array_get_idx(pd->json, i);
722 _ejson_model_child_new(pd, json, &i, cb);
723 }
724 break;
725 }
726 default:
727 ERR("Current type cannot have children: %d", pd->type);
728 }
729
730 unsigned int count = eina_list_count(pd->children_list);
731 if (count)
732 eo_do(pd->obj, eo_event_callback_call(EMODEL_EVENT_CHILDREN_COUNT_CHANGED, &count));
220} 733}
221 734
222static void 735static void
223_ejson_model_init(Ejson_Model_Data *pd) 736_ejson_model_child_new(Ejson_Model_Data *pd, json_object *json, void *data, Ejson_Model_Child_Data_New child_data_new)
224{ 737{
225 EINA_SAFETY_ON_NULL_RETURN(pd); 738 Ejson_Model_Type type = _ejson_model_type_from_json_object(json);
226 739
227 // TODO: Loads json_object 740 Eo *child = eo_add(EJSON_MODEL_CLASS,
741 pd->obj,
742 ejson_model_constructor(type));
228 743
229 EINA_SAFETY_ON_FALSE_RETURN(NULL != pd->json); 744 Ejson_Model_Data *child_pd = eo_data_scope_get(child, EJSON_MODEL_CLASS);
745 EINA_SAFETY_ON_NULL_RETURN(child_pd);
746
747 child_pd->json = json_object_get(json);
748
749 Ejson_Model_Child_Data *child_data = child_data_new(data);
750 _ejson_model_child_add(pd, child_pd, child_data);
751
752 eo_do(child, eo_event_callback_add(EMODEL_EVENT_PROPERTIES_CHANGED,
753 _ejson_model_child_properties_changed_cb,
754 pd));
755}
756
757static Ejson_Model_Type
758_ejson_model_type_get(Eo *obj EINA_UNUSED, Ejson_Model_Data *pd)
759{
760 DBG("(%p)", obj);
761 return pd->type;
230} 762}
231 763
232static void 764static void
233_ejson_model_shutdown(Ejson_Model_Data *pd) 765_ejson_model_type_set(Eo *obj EINA_UNUSED, Ejson_Model_Data *pd, const Ejson_Model_Type value)
234{ 766{
235 EINA_SAFETY_ON_NULL_RETURN(pd); 767 DBG("(%p)", obj);
236 json_object_put(pd->json); 768 EINA_SAFETY_ON_FALSE_RETURN(value >= 0 && value <= EJSON_MODEL_TYPE_ARRAY);
237 pd->json = NULL; 769 pd->type = value;
770}
771
772static bool
773_ejson_model_init(Ejson_Model_Data *pd)
774{
775 if (pd->json)
776 return true;
777
778 if (pd->stream)
779 {
780 if (!_ejson_model_stream_load(pd))
781 return false;
782 }
783 else
784 {
785 switch (pd->type)
786 {
787 case EJSON_MODEL_TYPE_OBJECT:
788 pd->json = json_object_new_object();
789 break;
790 case EJSON_MODEL_TYPE_ARRAY:
791 pd->json = json_object_new_array();
792 break;
793 default: break;
794 }
795 }
796
797 return true;
238} 798}
239 799
240static void 800static void
241_ejson_model_clear(Ejson_Model_Data *pd) 801_ejson_model_clear(Ejson_Model_Data *pd)
242{ 802{
243 EINA_SAFETY_ON_NULL_RETURN(pd); 803 EINA_SAFETY_ON_NULL_RETURN(pd);
244 if (!pd->json) 804
245 return; 805 eina_hash_free_buckets(pd->children_hash);
246 806
247 Eo *child; 807 Eo *child;
248 EINA_LIST_FREE(pd->children_list, child) 808 EINA_LIST_FREE(pd->children_list, child)
249 eo_unref(child); 809 eo_del(child);
250 810
251 //Eldbus_Pending *pending; 811 eina_value_free(pd->properties);
252 //EINA_LIST_FREE(pd->pending_list, pending) 812 pd->properties = NULL;
253 // eldbus_pending_cancel(pending);
254 813
255 if (pd->properties_array) 814 if (pd->properties_array)
256 { 815 {
@@ -258,7 +817,235 @@ _ejson_model_clear(Ejson_Model_Data *pd)
258 pd->properties_array = NULL; 817 pd->properties_array = NULL;
259 } 818 }
260 819
261 _ejson_model_shutdown(pd); 820 json_object_put(pd->json);
821 pd->json = NULL;
822 pd->json_property_valid = false;
823
824 free(pd->stream);
825 pd->stream = NULL;
826}
827
828typedef struct _Ejson_Model_Properties_Setup
829{
830 Ejson_Model_Data *pd;
831 const char *member_name[3];
832 const Eina_Value_Type *member_type[3];
833} Ejson_Model_Properties_Setup;
834
835static void
836_ejson_model_properties_setup(Ejson_Model_Data *pd)
837{
838 DBG("(%p) Setup type: %d", pd->obj, pd->type);
839
840 Ejson_Model_Properties_Setup setup = {.pd = pd};
841
842 setup.member_name[0] = EJSON_MODEL_JSON_PROPERTY;
843 setup.member_type[0] = EINA_VALUE_TYPE_STRING;
844 unsigned int member_count = 1;
845
846 switch (pd->type)
847 {
848 case EJSON_MODEL_TYPE_BOOLEAN:
849 setup.member_type[member_count] = EINA_VALUE_TYPE_INT;
850 break;
851 case EJSON_MODEL_TYPE_INT:
852 setup.member_type[member_count] = EINA_VALUE_TYPE_INT64;
853 break;
854 case EJSON_MODEL_TYPE_DOUBLE:
855 setup.member_type[member_count] = EINA_VALUE_TYPE_DOUBLE;
856 break;
857 case EJSON_MODEL_TYPE_STRING:
858 setup.member_type[member_count] = EINA_VALUE_TYPE_STRING;
859 break;
860 case EJSON_MODEL_TYPE_NULL:
861 case EJSON_MODEL_TYPE_OBJECT:
862 case EJSON_MODEL_TYPE_ARRAY:
863 break;
864 }
865
866 switch (pd->type)
867 {
868 case EJSON_MODEL_TYPE_BOOLEAN:
869 case EJSON_MODEL_TYPE_INT:
870 case EJSON_MODEL_TYPE_DOUBLE:
871 case EJSON_MODEL_TYPE_STRING:
872 setup.member_name[member_count] = EJSON_MODEL_VALUE_PROPERTY;
873 ++member_count;
874 break;
875 case EJSON_MODEL_TYPE_NULL:
876 case EJSON_MODEL_TYPE_OBJECT:
877 case EJSON_MODEL_TYPE_ARRAY:
878 break;
879 }
880
881 Ejson_Model_Type parent_type = _ejson_model_parent_type_get(pd);
882
883 if (EJSON_MODEL_TYPE_OBJECT == parent_type)
884 {
885 setup.member_name[member_count] = EJSON_MODEL_NAME_PROPERTY;
886 setup.member_type[member_count] = EINA_VALUE_TYPE_STRING;
887 ++member_count;
888 }
889
890 pd->properties_array = eina_array_new(member_count);
891 pd->properties_desc = emodel_value_struct_desc_new(member_count, _ejson_model_properties_setup_cb, &setup);
892 pd->properties = eina_value_struct_new(pd->properties_desc);
893 DBG("(%p) Properties setup done", pd->obj);
894}
895
896static void
897_ejson_model_properties_setup_cb(void *data, int index, Eina_Value_Struct_Member *member)
898{
899 Ejson_Model_Properties_Setup *setup = (Ejson_Model_Properties_Setup*)data;
900 member->name = eina_stringshare_add(setup->member_name[index]);
901 member->type = setup->member_type[index];
902 eina_array_push(setup->pd->properties_array, setup->member_name[index]);
903}
904
905static Ejson_Model_Type
906_ejson_model_parent_type_get(Ejson_Model_Data *pd)
907{
908 Eo *parent = eo_do(pd->obj, eo_parent_get());
909 if (!parent)
910 return EJSON_MODEL_TYPE_NULL;
911
912 Ejson_Model_Data *parent_pd = eo_data_scope_get(parent, EJSON_MODEL_CLASS);
913 EINA_SAFETY_ON_NULL_RETURN_VAL(parent_pd, EJSON_MODEL_TYPE_NULL);
914
915 return parent_pd->type;
916}
917
918static void
919_ejson_model_children_hash_free(void *data)
920{
921 Ejson_Model_Child_Data *child = (Ejson_Model_Child_Data*)data;
922 eina_stringshare_del(child->name);
923 free(child);
924}
925
926static void
927_ejson_model_invalidate(Ejson_Model_Data *pd)
928{
929 Eo *parent = pd->obj;
930 while ((parent = eo_do(parent, eo_parent_get())))
931 {
932 Ejson_Model_Data *parent_pd = eo_data_scope_get(parent, EJSON_MODEL_CLASS);
933 parent_pd->json_property_valid = false;
934
935 Emodel_Property_Event evt = {.invalidated_properties = parent_pd->properties_calc};
936 eo_do(parent, eo_event_callback_call(EMODEL_EVENT_PROPERTIES_CHANGED, &evt));
937 }
938
939 pd->json_property_valid = false;
940}
941
942static bool
943_ejson_model_stream_load(Ejson_Model_Data *pd)
944{
945 enum json_tokener_error error;
946 pd->json = json_tokener_parse_verbose(pd->stream, &error);
947 if (json_tokener_success != error)
948 {
949 ERR("Invalid json stream. Error: %d, stream = %s", error, pd->stream);
950 return false;
951 }
952
953 pd->type = _ejson_model_type_from_json_object(pd->json);
954 return true;
955}
956
957static Ejson_Model_Type
958_ejson_model_type_from_json_object(json_object *json)
959{
960 json_type type = json_object_get_type(json);
961 switch (type)
962 {
963 case json_type_null: return EJSON_MODEL_TYPE_NULL;
964 case json_type_boolean: return EJSON_MODEL_TYPE_BOOLEAN;
965 case json_type_double: return EJSON_MODEL_TYPE_DOUBLE;
966 case json_type_int: return EJSON_MODEL_TYPE_INT;
967 case json_type_object: return EJSON_MODEL_TYPE_OBJECT;
968 case json_type_array: return EJSON_MODEL_TYPE_ARRAY;
969 case json_type_string: return EJSON_MODEL_TYPE_STRING;
970 default:
971 ERR("Unrecognized type: %d", type);
972 return EJSON_MODEL_TYPE_NULL;
973 }
974}
975
976static Eina_Bool
977_ejson_model_eina_value_as(Eina_Value *value, const Eina_Value_Type *type, void *mem)
978{
979 const Eina_Value_Type * const value_type = eina_value_type_get(value);
980 EINA_SAFETY_ON_NULL_RETURN_VAL(value_type, false);
981
982 if (value_type == type)
983 return eina_value_get(value, mem);
984
985 Eina_Value convert;
986 Eina_Bool ret = eina_value_setup(&convert, type)
987 && eina_value_convert(value, &convert)
988 && eina_value_get(&convert, mem);
989 eina_value_flush(&convert);
990
991 return ret;
992}
993
994static Ejson_Model_Child_Data *
995_ejson_model_object_child_data_new(const char *name)
996{
997 Ejson_Model_Child_Data *child_data = calloc(1, sizeof(Ejson_Model_Child_Data));
998 EINA_SAFETY_ON_NULL_RETURN_VAL(child_data, NULL);
999 child_data->name = eina_stringshare_add(name);
1000
1001 return child_data;
1002}
1003
1004static Ejson_Model_Child_Data *
1005_ejson_model_array_child_data_new(int *index)
1006{
1007 Ejson_Model_Child_Data *child_data = calloc(1, sizeof(Ejson_Model_Child_Data));
1008 EINA_SAFETY_ON_NULL_RETURN_VAL(child_data, NULL);
1009 child_data->index = *index;
1010
1011 return child_data;
1012}
1013
1014static bool
1015_ejson_model_object_child_add(Ejson_Model_Data *pd, Ejson_Model_Data *child_pd, const char *name)
1016{
1017 Ejson_Model_Child_Data *child_data = _ejson_model_object_child_data_new(name);
1018 EINA_SAFETY_ON_NULL_RETURN_VAL(child_data, false);
1019
1020 return _ejson_model_child_add(pd, child_pd, child_data);
1021}
1022
1023static bool
1024_ejson_model_array_child_add(Ejson_Model_Data *pd, Ejson_Model_Data *child_pd, int index)
1025{
1026 Ejson_Model_Child_Data *child_data = _ejson_model_array_child_data_new(&index);
1027 EINA_SAFETY_ON_NULL_RETURN_VAL(child_data, false);
1028
1029 return _ejson_model_child_add(pd, child_pd, child_data);
1030}
1031
1032static bool
1033_ejson_model_child_add(Ejson_Model_Data *pd, Ejson_Model_Data *child_pd, Ejson_Model_Child_Data *child_data)
1034{
1035 EINA_SAFETY_ON_NULL_RETURN_VAL(pd, false);
1036 EINA_SAFETY_ON_NULL_RETURN_VAL(child_pd, false);
1037 EINA_SAFETY_ON_NULL_RETURN_VAL(child_data, false);
1038
1039 DBG("(%p) Adding new child %p of type: %d", pd->obj, child_pd->obj, child_pd->type);
1040 pd->children_list = eina_list_append(pd->children_list, child_pd->obj);
1041
1042 Eina_Bool ret = eina_hash_add(pd->children_hash, &child_pd->obj, child_data);
1043 EINA_SAFETY_ON_FALSE_GOTO(ret, on_error);
1044 return true;
1045
1046on_error:
1047 free(child_data);
1048 return false;
262} 1049}
263 1050
264#include "ejson_model.eo.c" 1051#include "ejson_model.eo.c"
diff --git a/src/lib/ejson_model.eo b/src/lib/ejson_model.eo
index 8fc1170..218ed63 100644
--- a/src/lib/ejson_model.eo
+++ b/src/lib/ejson_model.eo
@@ -6,17 +6,17 @@ class Ejson.Model (Eo.Base, Emodel) {
6 Custom Ejson_Model constructor. 6 Custom Ejson_Model constructor.
7 @def ejson_model_constructor 7 @def ejson_model_constructor
8 @since 1.13 8 @since 1.13
9 @in filename 9 @in type
10 */ 10 */
11 params { 11 params {
12 @in const(char) *filename; /*@ Remote filename of dbus */ 12 @in Ejson_Model_Type type; /*@ Json object type */
13 } 13 }
14 } 14 }
15 } 15 }
16 properties { 16 properties {
17 filename { 17 type {
18 values { 18 values {
19 const(char) *value; 19 Ejson_Model_Type value;
20 } 20 }
21 } 21 }
22 } 22 }
diff --git a/src/lib/ejson_model_private.h b/src/lib/ejson_model_private.h
index 77ebb02..36bab35 100644
--- a/src/lib/ejson_model_private.h
+++ b/src/lib/ejson_model_private.h
@@ -8,6 +8,8 @@
8 8
9#include <json.h> 9#include <json.h>
10 10
11#include <stdbool.h>
12
11typedef struct _Ejson_Model_Data Ejson_Model_Data; 13typedef struct _Ejson_Model_Data Ejson_Model_Data;
12 14
13/** 15/**
@@ -19,9 +21,14 @@ struct _Ejson_Model_Data
19 Emodel_Load load; 21 Emodel_Load load;
20 json_object *json; 22 json_object *json;
21 Eina_Array *properties_array; 23 Eina_Array *properties_array;
24 Eina_Value_Struct_Desc *properties_desc;
25 Eina_Value *properties;
22 Eina_List *children_list; 26 Eina_List *children_list;
23 Eina_Stringshare *filename; 27 Eina_Hash *children_hash;
24 //Eina_List *pending_list; 28 Ejson_Model_Type type;
29 Eina_Array *properties_calc;
30 bool json_property_valid;
31 char *stream;
25}; 32};
26 33
27#endif 34#endif
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
index a4c9a69..01b722e 100644
--- a/src/tests/Makefile.am
+++ b/src/tests/Makefile.am
@@ -1,11 +1,11 @@
1check_PROGRAMS = \ 1check_PROGRAMS = \
2 src/tests/esql_suite 2 src/tests/ejson_suite
3TESTS = src/tests/esql_suite 3TESTS = src/tests/ejson_suite
4 4
5src_tests_esql_suite_SOURCES = \ 5src_tests_ejson_suite_SOURCES = \
6 src/tests/ejson_suite.c \ 6 src/tests/ejson_suite.c \
7 src/tests/ejson_test_ejson_model.c 7 src/tests/ejson_test_ejson_model.c
8src_tests_esql_suite_CFLAGS = $(MOD_CFLAGS) \ 8src_tests_ejson_suite_CFLAGS = $(MOD_CFLAGS) \
9 -DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests\" 9 -DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests\"
10src_tests_esql_suite_LDADD = $(MOD_LIBS) $(CHECK_LIBS) 10src_tests_ejson_suite_LDADD = $(MOD_LIBS) $(CHECK_LIBS)
11 11
diff --git a/src/tests/ejson_suite.c b/src/tests/ejson_suite.c
index 29678b0..cd50da5 100644
--- a/src/tests/ejson_suite.c
+++ b/src/tests/ejson_suite.c
@@ -74,7 +74,7 @@ _init_logging(void)
74 74
75 //eina_log_domain_level_set("esskyuehl", EINA_LOG_LEVEL_DBG); 75 //eina_log_domain_level_set("esskyuehl", EINA_LOG_LEVEL_DBG);
76 //eina_log_domain_level_set("ejson_model", EINA_LOG_LEVEL_DBG); 76 //eina_log_domain_level_set("ejson_model", EINA_LOG_LEVEL_DBG);
77 //eina_log_domain_level_set("test_ejson_model", EINA_LOG_LEVEL_DBG); 77 eina_log_domain_level_set("test_ejson_model", EINA_LOG_LEVEL_DBG);
78} 78}
79 79
80static void 80static void
diff --git a/src/tests/ejson_test_ejson_model.c b/src/tests/ejson_test_ejson_model.c
index 4cbd211..ec01d0a 100644
--- a/src/tests/ejson_test_ejson_model.c
+++ b/src/tests/ejson_test_ejson_model.c
@@ -9,6 +9,8 @@
9#include <Eina.h> 9#include <Eina.h>
10#include <Ejson.h> 10#include <Ejson.h>
11 11
12#include <stdbool.h>
13
12static void 14static void
13_setup(void) 15_setup(void)
14{ 16{
@@ -16,15 +18,709 @@ _setup(void)
16 ck_assert_int_ge(ret, 1); 18 ck_assert_int_ge(ret, 1);
17} 19}
18 20
19void 21static void
20_teardown(void) 22_teardown(void)
21{ 23{
22 int ret = ejson_shutdown(); 24 int ret = ejson_shutdown();
23 ck_assert_int_eq(ret, 0); 25 ck_assert_int_eq(ret, 0);
24} 26}
25 27
28static Eina_Bool
29_eo_event_load_status_cb(void *data, Eo *obj EINA_UNUSED,
30 const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
31{
32 Emodel_Load_Status expected_status = *((Emodel_Load_Status*)data);
33 Emodel_Load load = *((Emodel_Load*)event_info);
34 if ((load.status & expected_status) != expected_status)
35 return EINA_TRUE;
36
37 ecore_main_loop_quit();
38 return EINA_FALSE;
39}
40
41static void
42_wait_until_load_status(Emodel *emodel, Emodel_Load_Status expected_status)
43{
44 Emodel_Load_Status actual_status = eo_do(emodel, emodel_load_status_get());
45 if (expected_status == actual_status) return;
46
47 eo_do(emodel, eo_event_callback_add(EMODEL_EVENT_LOAD_STATUS, _eo_event_load_status_cb, &expected_status));
48 ecore_main_loop_begin();
49 eo_do(emodel, eo_event_callback_del(EMODEL_EVENT_LOAD_STATUS, _eo_event_load_status_cb, &expected_status));
50}
51
52static void
53_check_json_string(Emodel *model, const char *expected_json_string)
54{
55 Eina_Value json_value;
56 Emodel_Load_Status status = eo_do(model, emodel_property_get(EJSON_MODEL_JSON_PROPERTY, &json_value));
57 ck_assert_int_eq(EMODEL_LOAD_STATUS_LOADED_PROPERTIES, status & EMODEL_LOAD_STATUS_LOADED_PROPERTIES);
58
59 const char *actual_json_string;
60 fail_unless(eina_value_get(&json_value, &actual_json_string));
61
62 ck_assert_str_eq(expected_json_string, actual_json_string);
63 eina_value_flush(&json_value);
64}
65
66static void
67_check_value_type_cannot_have_children(Emodel *model)
68{
69 Emodel *child = eo_do(model, emodel_child_add());
70 ck_assert_ptr_eq(NULL, child);
71}
72
73static Emodel_Load_Status
74_json_property_set(Emodel *model, const char *v)
75{
76 Eina_Value json;
77 eina_value_setup(&json, EINA_VALUE_TYPE_STRING);
78 eina_value_set(&json, v);
79 Emodel_Load_Status status = eo_do(model, emodel_property_set(EJSON_MODEL_JSON_PROPERTY, json));
80 eina_value_flush(&json);
81 return status;
82}
83
84static void
85_check_name_property_set(Emodel *model, const char *v)
86{
87 Eina_Value name;
88 eina_value_setup(&name, EINA_VALUE_TYPE_STRING);
89 eina_value_set(&name, v);
90 Emodel_Load_Status status = eo_do(model, emodel_property_set(EJSON_MODEL_NAME_PROPERTY, name));
91 ck_assert_int_eq(EMODEL_LOAD_STATUS_LOADED, status);
92 eina_value_flush(&name);
93}
94
95static void
96_check_int_value_property_set(Emodel *model, int64_t v)
97{
98 Eina_Value value;
99 eina_value_setup(&value, EINA_VALUE_TYPE_INT64);
100 eina_value_set(&value, v);
101
102 Emodel_Load_Status status = eo_do(model, emodel_property_set(EJSON_MODEL_VALUE_PROPERTY, value));
103 ck_assert_int_eq(EMODEL_LOAD_STATUS_LOADED, status);
104
105 char buf[64];
106 snprintf(buf, sizeof(buf), "%lld", v);
107
108 _check_json_string(model, buf);
109
110 eina_value_flush(&value);
111}
112
113static void
114_check_bool_value_property_set(Emodel *model, bool v)
115{
116 Eina_Value value;
117 eina_value_setup(&value, EINA_VALUE_TYPE_INT);
118 eina_value_set(&value, (int)v);
119
120 Emodel_Load_Status status = eo_do(model, emodel_property_set(EJSON_MODEL_VALUE_PROPERTY, value));
121 ck_assert_int_eq(EMODEL_LOAD_STATUS_LOADED, status);
122
123 _check_json_string(model, v ? "true" : "false");
124
125 eina_value_flush(&value);
126}
127
128static void
129_check_string_value_property_set(Emodel *model, const char *v)
130{
131 Eina_Value value;
132 eina_value_setup(&value, EINA_VALUE_TYPE_STRING);
133 eina_value_set(&value, v);
134
135 Emodel_Load_Status status = eo_do(model, emodel_property_set(EJSON_MODEL_VALUE_PROPERTY, value));
136 ck_assert_int_eq(EMODEL_LOAD_STATUS_LOADED, status);
137
138 size_t len = 1 + strlen(v) + 1 + 1;
139 char buf[len];
140 snprintf(buf, len, "\"%s\"", v);
141
142 _check_json_string(model, buf);
143
144 eina_value_flush(&value);
145}
146
147static void
148_check_emodel_children_count_eq(Emodel *model, unsigned int expected_children_count)
149{
150 unsigned int actual_children_count = 0;
151 eo_do(model, emodel_children_count_get(&actual_children_count));
152 ck_assert_int_eq(expected_children_count, actual_children_count);
153}
154
155static void
156_check_emodel_property_int_eq(Emodel *emodel, const char *property, int64_t expected_value)
157{
158 Eina_Value value;
159 Emodel_Load_Status status = eo_do(emodel, emodel_property_get(property, &value));
160 ck_assert_int_eq(EMODEL_LOAD_STATUS_LOADED, status);
161
162 const Eina_Value_Type *property_type = eina_value_type_get(&value);
163 ck_assert_ptr_eq(EINA_VALUE_TYPE_INT64, property_type);
164
165 int64_t actual_value = 0;
166 eina_value_get(&value, &actual_value);
167 ck_assert_int_eq(expected_value, actual_value);
168
169 eina_value_flush(&value);
170}
171
172static void
173_check_emodel_property_str_eq(Emodel *emodel, const char *property, const char *expected_value)
174{
175 Eina_Value value;
176 Emodel_Load_Status status = eo_do(emodel, emodel_property_get(property, &value));
177 ck_assert_int_eq(EMODEL_LOAD_STATUS_LOADED, status);
178
179 const Eina_Value_Type *property_type = eina_value_type_get(&value);
180 fail_if(EINA_VALUE_TYPE_STRING != property_type && EINA_VALUE_TYPE_STRINGSHARE != property_type);
181
182 const char *actual_value = NULL;
183 eina_value_get(&value, &actual_value);
184 ck_assert_str_eq(expected_value, actual_value);
185
186 eina_value_flush(&value);
187}
188
189static Emodel *
190_emodel_nth_child_get(Emodel *emodel, unsigned int n)
191{
192 Eina_Accessor *accessor;
193 Emodel_Load_Status status = eo_do(emodel, emodel_children_slice_get(n, 1, &accessor));
194 ck_assert_int_eq(EMODEL_LOAD_STATUS_LOADED, status);
195 ck_assert_ptr_ne(NULL, accessor);
196 Emodel *child = NULL;
197 Eina_Bool ret = eina_accessor_data_get(accessor, 0, (void**)&child);
198 eina_accessor_free(accessor);
199 ck_assert(ret);
200 ck_assert_ptr_ne(NULL, child);
201 return child;
202}
203
204static void
205_check_ejson_type(Emodel *model, Ejson_Model_Type expected_type)
206{
207 Ejson_Model_Type actual_type = eo_do(model, ejson_model_type_get());
208 ck_assert_int_eq(expected_type, actual_type);
209}
210
211static void
212_check_emodel_load(Emodel *model)
213{
214 eo_do(model, emodel_load());
215 _wait_until_load_status(model, EMODEL_LOAD_STATUS_LOADED);
216}
217
218static void
219_check_emodel_properties(Emodel *model, const char *expected_properties[])
220{
221 Eina_Array *properties = NULL;
222 Emodel_Load_Status status = eo_do(model, emodel_properties_list_get(&properties));
223 ck_assert_int_eq(EMODEL_LOAD_STATUS_LOADED, status);
224 ck_assert_ptr_ne(NULL, properties);
225
226 unsigned int actual_properties_count = eina_array_count(properties);
227
228 unsigned int expected_properties_count = 0;
229 const char *expected_property = NULL;
230 while ((expected_property = *expected_properties++))
231 {
232 const char *actual_property = eina_array_data_get(properties,
233 expected_properties_count);
234 ck_assert_str_eq(expected_property, actual_property);
235 ++expected_properties_count;
236 ck_assert_int_le(expected_properties_count, actual_properties_count);
237 }
238
239 ck_assert_int_eq(expected_properties_count, actual_properties_count);
240}
241
242static void
243_check_properties_count_eq(Emodel *model, unsigned int expected_properties_count)
244{
245 Eina_Array *properties = NULL;
246 Emodel_Load_Status status = eo_do(model, emodel_properties_list_get(&properties));
247 ck_assert_int_ne(EMODEL_LOAD_STATUS_ERROR, status);
248 if (!expected_properties_count && !properties)
249 return;
250
251 ck_assert_ptr_ne(NULL, properties);
252
253 unsigned int actual_properties_count = eina_array_count(properties);
254 ck_assert_int_eq(expected_properties_count, actual_properties_count);
255}
256
26START_TEST(smoke) 257START_TEST(smoke)
27{ 258{
259 Emodel *json = eo_add(EJSON_MODEL_CLASS, NULL,
260 ejson_model_constructor(EJSON_MODEL_TYPE_NULL));
261 ck_assert_ptr_ne(NULL, json);
262 eo_unref(json);
263}
264END_TEST
265
266START_TEST(load_object)
267{
268 Emodel *json = eo_add(EJSON_MODEL_CLASS, NULL,
269 ejson_model_constructor(EJSON_MODEL_TYPE_OBJECT));
270 ck_assert_ptr_ne(NULL, json);
271
272 _check_emodel_load(json);
273
274 eo_unref(json);
275}
276END_TEST
277
278START_TEST(object_property_set)
279{
280 Emodel *json = eo_add(EJSON_MODEL_CLASS, NULL,
281 ejson_model_constructor(EJSON_MODEL_TYPE_OBJECT));
282 ck_assert_ptr_ne(NULL, json);
283
284 _check_emodel_load(json);
285
286 _check_json_string(json, "{ }");
287
288 Emodel *child = eo_do(json, emodel_child_add());
289 ck_assert_ptr_ne(NULL, child);
290
291 _check_json_string(json, "{ }");
292
293 Ejson_Model_Type type = eo_do(child, ejson_model_type_get());
294 ck_assert_int_eq(EJSON_MODEL_TYPE_NULL, type);
295 eo_do(child, ejson_model_type_set(EJSON_MODEL_TYPE_INT));
296 type = eo_do(child, ejson_model_type_get());
297 ck_assert_int_eq(EJSON_MODEL_TYPE_INT, type);
298
299 _check_emodel_load(child);
300
301 _check_json_string(child, "null");
302 _check_json_string(json, "{ }");
303
304 // set member name
305 _check_name_property_set(child, "a");
306 _check_json_string(child, "null");
307 _check_json_string(json, "{ \"a\": null }");
308
309 // set member value
310 _check_int_value_property_set(child, 1234);
311 _check_json_string(json, "{ \"a\": 1234 }");
312
313 // change member name
314 _check_name_property_set(child, "b");
315 _check_json_string(json, "{ \"b\": 1234 }");
316
317 eo_unref(json);
318}
319END_TEST
320
321START_TEST(array_object_property_set)
322{
323 Emodel *json = eo_add(EJSON_MODEL_CLASS, NULL,
324 ejson_model_constructor(EJSON_MODEL_TYPE_ARRAY));
325 ck_assert_ptr_ne(NULL, json);
326
327 _check_emodel_load(json);
328
329 _check_json_string(json, "[ ]");
330
331 Emodel *child = eo_do(json, emodel_child_add());
332 ck_assert_ptr_ne(NULL, child);
333
334 _check_json_string(json, "[ ]");
335
336 Ejson_Model_Type type = eo_do(child, ejson_model_type_get());
337 ck_assert_int_eq(EJSON_MODEL_TYPE_NULL, type);
338 eo_do(child, ejson_model_type_set(EJSON_MODEL_TYPE_INT));
339 type = eo_do(child, ejson_model_type_get());
340 ck_assert_int_eq(EJSON_MODEL_TYPE_INT, type);
341
342 _check_emodel_load(child);
343
344 _check_json_string(child, "null");
345 _check_json_string(json, "[ ]");
346
347 _check_int_value_property_set(child, 1234);
348
349 _check_json_string(json, "[ 1234 ]");
350
351 eo_unref(json);
352}
353END_TEST
354
355START_TEST(int_property_set)
356{
357 Emodel *json = eo_add(EJSON_MODEL_CLASS, NULL,
358 ejson_model_constructor(EJSON_MODEL_TYPE_INT));
359 ck_assert_ptr_ne(NULL, json);
360
361 _check_emodel_load(json);
362
363 _check_json_string(json, "null");
364
365 _check_int_value_property_set(json, 1234);
366
367 _check_value_type_cannot_have_children(json);
368
369 eo_unref(json);
370}
371END_TEST
372
373START_TEST(boolean_property_set)
374{
375 Emodel *json = eo_add(EJSON_MODEL_CLASS, NULL,
376 ejson_model_constructor(EJSON_MODEL_TYPE_BOOLEAN));
377 ck_assert_ptr_ne(NULL, json);
378
379 _check_emodel_load(json);
380
381 _check_json_string(json, "null");
382
383 _check_bool_value_property_set(json, true);
384 _check_bool_value_property_set(json, false);
385
386 _check_value_type_cannot_have_children(json);
387
388 eo_unref(json);
389}
390END_TEST
391
392START_TEST(string_property_set)
393{
394 Emodel *json = eo_add(EJSON_MODEL_CLASS, NULL,
395 ejson_model_constructor(EJSON_MODEL_TYPE_STRING));
396 ck_assert_ptr_ne(NULL, json);
397
398 _check_emodel_load(json);
399
400 _check_json_string(json, "null");
401
402 _check_string_value_property_set(json, "Hello world!");
403
404 _check_value_type_cannot_have_children(json);
405
406 eo_unref(json);
407}
408END_TEST
409
410START_TEST(json_object_property_set)
411{
412 Emodel *json = eo_add(EJSON_MODEL_CLASS, NULL,
413 ejson_model_constructor(EJSON_MODEL_TYPE_NULL));
414 ck_assert_ptr_ne(NULL, json);
415
416 _json_property_set(json, "{ \"a\": 1, \"b\": \"Hello\" }");
417
418 _check_emodel_load(json);
419
420 _check_json_string(json, "{ \"a\": 1, \"b\": \"Hello\" }");
421
422 _check_emodel_children_count_eq(json, 2);
423
424 Emodel *child1 = _emodel_nth_child_get(json, 1);
425 Emodel *child2 = _emodel_nth_child_get(json, 2);
426
427 _check_ejson_type(child1, EJSON_MODEL_TYPE_INT);
428 _check_ejson_type(child2, EJSON_MODEL_TYPE_STRING);
429
430 _check_emodel_load(child1);
431
432 _check_emodel_property_int_eq(child1, EJSON_MODEL_VALUE_PROPERTY, 1);
433 _check_emodel_property_str_eq(child1, EJSON_MODEL_NAME_PROPERTY, "a");
434
435 _check_emodel_load(child2);
436
437 _check_emodel_property_str_eq(child2, EJSON_MODEL_VALUE_PROPERTY, "Hello");
438 _check_emodel_property_str_eq(child2, EJSON_MODEL_NAME_PROPERTY, "b");
439
440 _json_property_set(child2, "{ \"c\": 2, \"d\": \"World\" }");
441
442 _check_json_string(json, "{ \"a\": 1, \"b\": { \"c\": 2, \"d\": \"World\" } }");
443
444 eo_unref(json);
445}
446END_TEST
447
448START_TEST(json_array_property_set)
449{
450 Emodel *json = eo_add(EJSON_MODEL_CLASS, NULL,
451 ejson_model_constructor(EJSON_MODEL_TYPE_NULL));
452 ck_assert_ptr_ne(NULL, json);
453
454 _json_property_set(json, "[ 1, \"Hello\" ]");
455
456 _check_emodel_load(json);
457
458 _check_json_string(json, "[ 1, \"Hello\" ]");
459
460 _check_emodel_children_count_eq(json, 2);
461
462 Emodel *child1 = _emodel_nth_child_get(json, 1);
463 Emodel *child2 = _emodel_nth_child_get(json, 2);
464
465 _check_ejson_type(child1, EJSON_MODEL_TYPE_INT);
466 _check_ejson_type(child2, EJSON_MODEL_TYPE_STRING);
467
468 _check_emodel_load(child1);
469
470 _check_emodel_property_int_eq(child1, EJSON_MODEL_VALUE_PROPERTY, 1);
471
472 _check_emodel_load(child2);
473
474 _check_emodel_property_str_eq(child2, EJSON_MODEL_VALUE_PROPERTY, "Hello");
475
476 _json_property_set(child2, "[ 2, \"World\" ]");
477
478 _check_json_string(json, "[ 1, [ 2, \"World\" ] ]");
479
480 eo_unref(json);
481}
482END_TEST
483
484START_TEST(load_status_get)
485{
486 Emodel *json = eo_add(EJSON_MODEL_CLASS, NULL,
487 ejson_model_constructor(EJSON_MODEL_TYPE_NULL));
488 ck_assert_ptr_ne(NULL, json);
489
490 Emodel_Load_Status status = eo_do(json, emodel_load_status_get());
491 ck_assert_int_eq(EMODEL_LOAD_STATUS_UNLOADED, status);
492
493 _check_emodel_load(json);
494
495 status = eo_do(json, emodel_load_status_get());
496 ck_assert_int_eq(EMODEL_LOAD_STATUS_LOADED, status);
497
498 eo_unref(json);
499}
500END_TEST
501
502static const char *_all_json_types_object_string =
503 "{ \"i\": 1, "
504 "\"s\": \"Hello World!\", "
505 "\"b\": true, "
506 "\"d\": 1.234, "
507 "\"n\": null, "
508 "\"o\": { }, "
509 "\"a\": [ ] "
510 "}";
511
512static Emodel *
513_create_model_with_all_json_types()
514{
515 Emodel *json = eo_add(EJSON_MODEL_CLASS, NULL,
516 ejson_model_constructor(EJSON_MODEL_TYPE_NULL));
517 ck_assert_ptr_ne(NULL, json);
518
519 _check_emodel_load(json);
520
521 _json_property_set(json, _all_json_types_object_string);
522 _check_json_string(json, _all_json_types_object_string);
523
524 _check_emodel_children_count_eq(json, 7);
525 return json;
526}
527
528START_TEST(properties_list_get)
529{
530 Emodel *json = _create_model_with_all_json_types();
531
532 _check_emodel_properties(json, (const char*[]){"json", NULL});
533
534 Emodel *child_i = _emodel_nth_child_get(json, 1);
535 Emodel *child_s = _emodel_nth_child_get(json, 2);
536 Emodel *child_b = _emodel_nth_child_get(json, 3);
537 Emodel *child_d = _emodel_nth_child_get(json, 4);
538 Emodel *child_n = _emodel_nth_child_get(json, 5);
539 Emodel *child_o = _emodel_nth_child_get(json, 6);
540 Emodel *child_a = _emodel_nth_child_get(json, 7);
541
542 _check_emodel_load(child_i);
543 _check_emodel_load(child_s);
544 _check_emodel_load(child_b);
545 _check_emodel_load(child_d);
546 _check_emodel_load(child_n);
547 _check_emodel_load(child_o);
548 _check_emodel_load(child_a);
549
550 _check_ejson_type(child_i, EJSON_MODEL_TYPE_INT);
551 _check_ejson_type(child_s, EJSON_MODEL_TYPE_STRING);
552 _check_ejson_type(child_b, EJSON_MODEL_TYPE_BOOLEAN);
553 _check_ejson_type(child_d, EJSON_MODEL_TYPE_DOUBLE);
554 _check_ejson_type(child_n, EJSON_MODEL_TYPE_NULL);
555 _check_ejson_type(child_o, EJSON_MODEL_TYPE_OBJECT);
556 _check_ejson_type(child_a, EJSON_MODEL_TYPE_ARRAY);
557
558 _check_emodel_properties(child_i, (const char*[]){"json", "value", "name", NULL});
559 _check_emodel_properties(child_s, (const char*[]){"json", "value", "name", NULL});
560 _check_emodel_properties(child_b, (const char*[]){"json", "value", "name", NULL});
561 _check_emodel_properties(child_d, (const char*[]){"json", "value", "name", NULL});
562 _check_emodel_properties(child_n, (const char*[]){"json", "name", NULL});
563 _check_emodel_properties(child_o, (const char*[]){"json", "name", NULL});
564 _check_emodel_properties(child_a, (const char*[]){"json", "name", NULL});
565
566 eo_unref(json);
567}
568END_TEST
569
570START_TEST(unload)
571{
572 Emodel *json = _create_model_with_all_json_types();
573
574 eo_do(json, emodel_unload());
575 _wait_until_load_status(json, EMODEL_LOAD_STATUS_UNLOADED);
576
577 // reload
578 _check_emodel_load(json);
579 _check_json_string(json, "{ }");
580
581 _json_property_set(json, _all_json_types_object_string);
582 _check_json_string(json, _all_json_types_object_string);
583
584 eo_unref(json);
585}
586END_TEST
587
588START_TEST(properties_load)
589{
590 Emodel *json = eo_add(EJSON_MODEL_CLASS, NULL,
591 ejson_model_constructor(EJSON_MODEL_TYPE_NULL));
592 ck_assert_ptr_ne(NULL, json);
593
594 _json_property_set(json, _all_json_types_object_string);
595
596 eo_do(json, emodel_properties_load());
597 _wait_until_load_status(json, EMODEL_LOAD_STATUS_LOADED_PROPERTIES);
598
599 _check_emodel_children_count_eq(json, 0);
600
601 _check_json_string(json, _all_json_types_object_string);
602
603 eo_unref(json);
604}
605END_TEST
606
607START_TEST(children_load)
608{
609 Emodel *json = eo_add(EJSON_MODEL_CLASS, NULL,
610 ejson_model_constructor(EJSON_MODEL_TYPE_NULL));
611 ck_assert_ptr_ne(NULL, json);
612
613 _json_property_set(json, _all_json_types_object_string);
614
615 eo_do(json, emodel_children_load());
616 _wait_until_load_status(json, EMODEL_LOAD_STATUS_LOADED_CHILDREN);
617
618 _check_emodel_children_count_eq(json, 7);
619
620 _check_properties_count_eq(json, 0);
621
622 eo_unref(json);
623}
624END_TEST
625
626
627START_TEST(object_child_del)
628{
629 Emodel *json = _create_model_with_all_json_types();
630
631 Emodel *child_i = _emodel_nth_child_get(json, 1);
632 Emodel *child_s = _emodel_nth_child_get(json, 2);
633 Emodel *child_b = _emodel_nth_child_get(json, 3);
634 Emodel *child_d = _emodel_nth_child_get(json, 4);
635 Emodel *child_n = _emodel_nth_child_get(json, 5);
636 Emodel *child_o = _emodel_nth_child_get(json, 6);
637 Emodel *child_a = _emodel_nth_child_get(json, 7);
638
639 eo_do(json, emodel_child_del(child_s));
640 _check_emodel_children_count_eq(json, 6);
641 _check_json_string(json, "{ \"i\": 1, \"b\": true, \"d\": 1.234, \"n\": null, \"o\": { }, \"a\": [ ] }");
642
643 eo_do(json, emodel_child_del(child_i));
644 _check_emodel_children_count_eq(json, 5);
645 _check_json_string(json, "{ \"b\": true, \"d\": 1.234, \"n\": null, \"o\": { }, \"a\": [ ] }");
646
647 eo_do(json, emodel_child_del(child_a));
648 _check_emodel_children_count_eq(json, 4);
649 _check_json_string(json, "{ \"b\": true, \"d\": 1.234, \"n\": null, \"o\": { } }");
650
651 eo_do(json, emodel_child_del(child_d));
652 _check_emodel_children_count_eq(json, 3);
653 _check_json_string(json, "{ \"b\": true, \"n\": null, \"o\": { } }");
654
655 eo_do(json, emodel_child_del(child_b));
656 _check_emodel_children_count_eq(json, 2);
657 _check_json_string(json, "{ \"n\": null, \"o\": { } }");
658
659 eo_do(json, emodel_child_del(child_o));
660 _check_emodel_children_count_eq(json, 1);
661 _check_json_string(json, "{ \"n\": null }");
662
663 eo_do(json, emodel_child_del(child_n));
664 _check_emodel_children_count_eq(json, 0);
665 _check_json_string(json, "{ }");
666
667 eo_unref(json);
668}
669END_TEST
670
671START_TEST(array_child_del)
672{
673 const char *_all_json_types_array_string =
674 "[ 1, \"Hello World!\", true, 1.234, null, { }, [ ] ]";
675
676 Emodel *json = eo_add(EJSON_MODEL_CLASS, NULL,
677 ejson_model_constructor(EJSON_MODEL_TYPE_NULL));
678 ck_assert_ptr_ne(NULL, json);
679
680 _check_emodel_load(json);
681
682 _json_property_set(json, _all_json_types_array_string);
683 _check_json_string(json, _all_json_types_array_string);
684
685 _check_emodel_children_count_eq(json, 7);
686
687 Emodel *child_i = _emodel_nth_child_get(json, 1);
688 Emodel *child_s = _emodel_nth_child_get(json, 2);
689 Emodel *child_b = _emodel_nth_child_get(json, 3);
690 Emodel *child_d = _emodel_nth_child_get(json, 4);
691 Emodel *child_n = _emodel_nth_child_get(json, 5);
692 Emodel *child_o = _emodel_nth_child_get(json, 6);
693 Emodel *child_a = _emodel_nth_child_get(json, 7);
694
695 eo_do(json, emodel_child_del(child_s));
696 _check_emodel_children_count_eq(json, 6);
697 _check_json_string(json, "[ 1, true, 1.234, null, { }, [ ] ]");
698
699 eo_do(json, emodel_child_del(child_i));
700 _check_emodel_children_count_eq(json, 5);
701 _check_json_string(json, "[ true, 1.234, null, { }, [ ] ]");
702
703 eo_do(json, emodel_child_del(child_a));
704 _check_emodel_children_count_eq(json, 4);
705 _check_json_string(json, "[ true, 1.234, null, { } ]");
706
707 eo_do(json, emodel_child_del(child_d));
708 _check_emodel_children_count_eq(json, 3);
709 _check_json_string(json, "[ true, null, { } ]");
710
711 eo_do(json, emodel_child_del(child_b));
712 _check_emodel_children_count_eq(json, 2);
713 _check_json_string(json, "[ null, { } ]");
714
715 eo_do(json, emodel_child_del(child_o));
716 _check_emodel_children_count_eq(json, 1);
717 _check_json_string(json, "[ null ]");
718
719 eo_do(json, emodel_child_del(child_n));
720 _check_emodel_children_count_eq(json, 0);
721 _check_json_string(json, "[ ]");
722
723 eo_unref(json);
28} 724}
29END_TEST 725END_TEST
30 726
@@ -33,15 +729,19 @@ ejson_test_ejson_model(TCase *tc)
33{ 729{
34 tcase_add_checked_fixture(tc, _setup, _teardown); 730 tcase_add_checked_fixture(tc, _setup, _teardown);
35 tcase_add_test(tc, smoke); 731 tcase_add_test(tc, smoke);
36 //tcase_add_test(tc, load_status_get); 732 tcase_add_test(tc, load_object);
37 //tcase_add_test(tc, properties_list_get); 733 tcase_add_test(tc, object_property_set);
38 //tcase_add_test(tc, property_get); 734 tcase_add_test(tc, array_object_property_set);
39 //tcase_add_test(tc, property_set); 735 tcase_add_test(tc, int_property_set);
40 //tcase_add_test(tc, children_count); 736 tcase_add_test(tc, boolean_property_set);
41 //tcase_add_test(tc, children_slice_get); 737 tcase_add_test(tc, string_property_set);
42 //tcase_add_test(tc, unload); 738 tcase_add_test(tc, json_object_property_set);
43 //tcase_add_test(tc, load); 739 tcase_add_test(tc, json_array_property_set);
44 //tcase_add_test(tc, properties_load); 740 tcase_add_test(tc, load_status_get);
45 //tcase_add_test(tc, children_load); 741 tcase_add_test(tc, properties_list_get);
46 //tcase_add_test(tc, child_del); 742 tcase_add_test(tc, unload);
743 tcase_add_test(tc, properties_load);
744 tcase_add_test(tc, children_load);
745 tcase_add_test(tc, object_child_del);
746 tcase_add_test(tc, array_child_del);
47} 747}