f52e18886ba91068380445c64ccbda8ddb7ea0df
[demo.git] / VES5.0 / evel / evel-library / code / evel_library / evel_other.c
1 /**************************************************************************//**
2  * @file
3  * Implementation of EVEL functions relating to Other.
4  *
5  * License
6  * -------
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice,
12  *    this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  *    this list of conditions and the following disclaimer in the documentation
15  *    and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:  This product includes
18  *    software developed by the AT&T.
19  * 4. Neither the name of AT&T nor the names of its contributors may be used to
20  *    endorse or promote products derived from this software without specific
21  *    prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
24  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
27  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *****************************************************************************/
34
35 #include <string.h>
36 #include <assert.h>
37 #include <stdlib.h>
38
39 #include "evel.h"
40 #include "evel_internal.h"
41
42 /**************************************************************************//**
43  * Create a new Other event.
44  *
45  * @note    The mandatory fields on the Other must be supplied to this factory
46  *          function and are immutable once set.  Optional fields have explicit
47  *          setter functions, but again values may only be set once so that the
48  *          Other has immutable properties.
49  * @returns pointer to the newly manufactured ::EVENT_OTHER.  If the event is
50  *          not used (i.e. posted) it must be released using ::evel_free_other.
51  * @retval  NULL  Failed to create the event.
52  *****************************************************************************/
53 EVENT_OTHER * evel_new_other()
54 {
55   EVENT_OTHER * other = NULL;
56   EVEL_ENTER();
57
58   /***************************************************************************/
59   /* Check preconditions.                                                    */
60   /***************************************************************************/
61
62   /***************************************************************************/
63   /* Allocate the Other.                                                     */
64   /***************************************************************************/
65   other = malloc(sizeof(EVENT_OTHER));
66   if (other == NULL)
67   {
68     log_error_state("Out of memory");
69     goto exit_label;
70   }
71   memset(other, 0, sizeof(EVENT_OTHER));
72   EVEL_DEBUG("New Other is at %lp", other);
73
74   /***************************************************************************/
75   /* Initialize the header & the Other fields.  Optional string values are   */
76   /* uninitialized (NULL).                                                   */
77   /***************************************************************************/
78   evel_init_header(&other->header,"OtherEvent");
79   other->header.event_domain = EVEL_DOMAIN_OTHER;
80   other->major_version = EVEL_OTHER_EVENT_MAJOR_VERSION;
81   other->minor_version = EVEL_OTHER_EVENT_MINOR_VERSION;
82
83   other->namedarrays = NULL;
84   dlist_initialize(&other->jsonobjects);
85   dlist_initialize(&other->namedvalues);
86
87 exit_label:
88   EVEL_EXIT();
89   return other;
90 }
91
92 /**************************************************************************//**
93  * Set the Event Type property of the Other.
94  *
95  * @note  The property is treated as immutable: it is only valid to call
96  *        the setter once.  However, we don't assert if the caller tries to
97  *        overwrite, just ignoring the update instead.
98  *
99  * @param other       Pointer to the Other.
100  * @param type        The Event Type to be set. ASCIIZ string. The caller
101  *                    does not need to preserve the value once the function
102  *                    returns.
103  *****************************************************************************/
104 void evel_other_type_set(EVENT_OTHER * other,
105                          const char * const type)
106 {
107   EVEL_ENTER();
108
109   /***************************************************************************/
110   /* Check preconditions and call evel_header_type_set.                      */
111   /***************************************************************************/
112   assert(other != NULL);
113   assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
114   evel_header_type_set(&other->header, type);
115
116   EVEL_EXIT();
117 }
118
119 /**************************************************************************//**
120  * Add a json object to jsonObject list.
121  *
122  * The name and value are null delimited ASCII strings.  The library takes
123  * a copy so the caller does not have to preserve values after the function
124  * returns.
125  *
126  * @param other         Pointer to the Other.
127  * @param size          size of hashtable
128  *****************************************************************************/
129 void evel_other_field_set_namedarraysize(EVENT_OTHER * other, const int size)
130 {
131   OTHER_FIELD * other_field = NULL;
132   EVEL_ENTER();
133
134   /***************************************************************************/
135   /* Check preconditions.                                                    */
136   /***************************************************************************/
137   assert(other != NULL);
138   assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
139   assert(other->namedarrays == NULL);
140   assert(size > 0);
141
142   EVEL_DEBUG("Adding Named array");
143
144   other->namedarrays =  ht_create(size);
145
146   EVEL_EXIT();
147 }
148
149
150 /**************************************************************************//**
151  * Add a json object to jsonObject list.
152  *
153  * The name and value are null delimited ASCII strings.  The library takes
154  * a copy so the caller does not have to preserve values after the function
155  * returns.
156  *
157  * @param other         Pointer to the Other.
158  * @param size          size of hashtable
159  *****************************************************************************/
160 void evel_other_field_add_namedarray(EVENT_OTHER * other, const char *hashname,  char * name, char *value)
161 {
162   OTHER_FIELD * other_field = NULL;
163   DLIST *list = NULL;
164   EVEL_ENTER();
165
166   /***************************************************************************/
167   /* Check preconditions.                                                    */
168   /***************************************************************************/
169   assert(other != NULL);
170   assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
171   assert(other->namedarrays != NULL);
172
173   EVEL_DEBUG("Adding values to Named array");
174       
175   EVEL_DEBUG("Adding name=%s value=%s", name, value);
176   other_field = malloc(sizeof(OTHER_FIELD));
177   assert(other_field != NULL);
178   memset(other_field, 0, sizeof(OTHER_FIELD));
179   other_field->name = strdup(name);
180   other_field->value = strdup(value);
181   assert(other_field->name != NULL);
182   assert(other_field->value != NULL);
183
184
185   list = ht_get(other->namedarrays, hashname);
186   if( list == NULL )
187   {
188      DLIST * nlist = malloc(sizeof(DLIST));
189      dlist_initialize(nlist);
190      dlist_push_last(nlist, other_field);
191      ht_set(other->namedarrays, hashname, nlist);
192      EVEL_DEBUG("Created to new table table");
193   }
194   else
195   {
196      dlist_push_last(list, other_field);
197      EVEL_DEBUG("Adding to existing table");
198   }
199
200   EVEL_EXIT();
201 }
202
203
204 /**************************************************************************//**
205  * Add a json object to jsonObject list.
206  *
207  * The name and value are null delimited ASCII strings.  The library takes
208  * a copy so the caller does not have to preserve values after the function
209  * returns.
210  *
211  * @param other     Pointer to the Other.
212  * @param jsonobj   Pointer to json object
213  *****************************************************************************/
214 void evel_other_field_add_jsonobj(EVENT_OTHER * other, EVEL_JSON_OBJECT *jsonobj)
215 {
216   OTHER_FIELD * other_field = NULL;
217   EVEL_ENTER();
218
219   /***************************************************************************/
220   /* Check preconditions.                                                    */
221   /***************************************************************************/
222   assert(other != NULL);
223   assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
224   assert(jsonobj != NULL);
225
226   EVEL_DEBUG("Adding jsonObject");
227
228   dlist_push_last(&other->jsonobjects, jsonobj);
229
230   EVEL_EXIT();
231 }
232
233 /**************************************************************************//**
234  * Add a field name/value pair to the Other.
235  *
236  * The name and value are null delimited ASCII strings.  The library takes
237  * a copy so the caller does not have to preserve values after the function
238  * returns.
239  *
240  * @param other     Pointer to the Other.
241  * @param name      ASCIIZ string with the field's name.  The caller does not
242  *                  need to preserve the value once the function returns.
243  * @param value     ASCIIZ string with the field's value.  The caller does not
244  *                  need to preserve the value once the function returns.
245  *****************************************************************************/
246 void evel_other_field_add(EVENT_OTHER * other, char * name, char * value)
247 {
248   OTHER_FIELD * other_field = NULL;
249   EVEL_ENTER();
250
251   /***************************************************************************/
252   /* Check preconditions.                                                    */
253   /***************************************************************************/
254   assert(other != NULL);
255   assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
256   assert(name != NULL);
257   assert(value != NULL);
258
259   EVEL_DEBUG("Adding name=%s value=%s", name, value);
260   other_field = malloc(sizeof(OTHER_FIELD));
261   assert(other_field != NULL);
262   memset(other_field, 0, sizeof(OTHER_FIELD));
263   other_field->name = strdup(name);
264   other_field->value = strdup(value);
265   assert(other_field->name != NULL);
266   assert(other_field->value != NULL);
267
268   dlist_push_last(&other->namedvalues, other_field);
269
270   EVEL_EXIT();
271 }
272
273 /**************************************************************************//**
274  * Encode the Other in JSON according to AT&T's schema for the event type.
275  *
276  * @param jbuf          Pointer to the ::EVEL_JSON_BUFFER to encode into.
277  * @param event         Pointer to the ::EVENT_HEADER to encode.
278  *****************************************************************************/
279 void evel_json_encode_other(EVEL_JSON_BUFFER * jbuf,
280                             EVENT_OTHER * event)
281 {
282   OTHER_FIELD * other_field = NULL;
283   EVEL_JSON_OBJECT * jsonobjp = NULL;
284   DLIST_ITEM * other_field_item = NULL;
285   EVEL_JSON_OBJECT_INSTANCE * jsonobjinst = NULL;
286   DLIST_ITEM * jsobj_field_item = NULL;
287   EVEL_INTERNAL_KEY * keyinst = NULL;
288   DLIST_ITEM * keyinst_field_item = NULL;
289   HASHTABLE_T *ht = NULL;
290   int i;
291   bool itm_added = false;
292   DLIST *itm_list = NULL;
293
294   EVEL_ENTER();
295
296   /***************************************************************************/
297   /* Check preconditions.                                                    */
298   /***************************************************************************/
299   assert(event != NULL);
300   assert(event->header.event_domain == EVEL_DOMAIN_OTHER);
301
302   evel_json_encode_header(jbuf, &event->header);
303   evel_json_open_named_object(jbuf, "otherFields");
304
305 // iterate through hashtable and print DLIST for each entry
306
307    ht = event->namedarrays;
308    if( ht != NULL )
309    {
310      if( ht->size > 0)
311      {
312         for( i = 0; i < ht->size; i++ ) {
313              if( ht->table[i] != NULL)
314              {
315                 itm_added = true;
316              }
317         }
318         if( itm_added == true)
319         {
320
321   if (evel_json_open_opt_named_list(jbuf, "hashOfNameValuePairArrays"))
322   {
323        for( i = 0; i < ht->size; i++ ) {
324              if( ht->table[i] != NULL)
325              {
326                 itm_list = ht->table[i];
327
328   if(evel_json_open_opt_named_list(jbuf, ht->table[i]->key))
329   {
330     other_field_item = dlist_get_first(&itm_list);
331     while (other_field_item != NULL)
332     {
333      other_field = (OTHER_FIELD *) other_field_item->item;
334      if(other_field != NULL){
335        evel_json_open_object(jbuf);
336        evel_enc_kv_string(jbuf, "name", other_field->name);
337        evel_enc_kv_string(jbuf, "value", other_field->value);
338        evel_json_close_object(jbuf);
339        other_field_item = dlist_get_next(other_field_item);
340      }
341     }
342     evel_json_close_list(jbuf);
343   }
344
345              }
346        }
347
348        evel_json_close_list(jbuf);
349   }
350
351
352         }
353      }
354    }
355
356   evel_json_checkpoint(jbuf);
357   if(evel_json_open_opt_named_list(jbuf, "jsonObjects"))
358   {
359   bool item_added = false;
360   other_field_item = dlist_get_first(&event->jsonobjects);
361   while (other_field_item != NULL)
362   {
363     jsonobjp = (EVEL_JSON_OBJECT *) other_field_item->item;
364     if(jsonobjp != NULL);
365     {
366      evel_json_open_object(jbuf);
367
368        if( evel_json_open_opt_named_list(jbuf, "objectInstances"))
369        {
370         bool item_added2 = false;
371         jsobj_field_item = dlist_get_first(&jsonobjp->jsonobjectinstances);
372         while (jsobj_field_item != NULL)
373         {
374            jsonobjinst = (EVEL_JSON_OBJECT_INSTANCE *) jsobj_field_item->item;
375            if( jsonobjinst != NULL )
376            {
377               evel_json_open_object(jbuf);
378               evel_enc_kv_object(jbuf, "objectInstance", jsonobjinst->jsonstring);
379               evel_enc_kv_ull(jbuf, "objectInstanceEpochMicrosec", jsonobjinst->objinst_epoch_microsec);
380   //evel_json_checkpoint(jbuf);
381   if (evel_json_open_opt_named_list(jbuf, "objectKeys"))
382   {
383     bool item_added3 = false;
384
385     keyinst_field_item = dlist_get_first(&jsonobjinst->object_keys);
386     while (keyinst_field_item != NULL)
387     {
388       keyinst = (EVEL_INTERNAL_KEY *)keyinst_field_item->item;
389       if(keyinst != NULL)
390       {
391         evel_json_open_object(jbuf);
392         evel_enc_kv_string(jbuf, "keyName", keyinst->keyname);
393         evel_enc_kv_opt_int(jbuf, "keyOrder", &keyinst->keyorder);
394         evel_enc_kv_opt_string(jbuf, "keyValue", &keyinst->keyvalue);
395         evel_json_close_object(jbuf);
396         item_added3 = false;
397       }
398       keyinst_field_item = dlist_get_next(keyinst_field_item);
399     }
400     evel_json_close_list(jbuf);
401
402     /*************************************************************************/
403     /* If we've not written anything, rewind to before we opened the list.   */
404     /*************************************************************************/
405     //if (!item_added3)
406     //{
407     //  evel_json_rewind(jbuf);
408     //}
409   }
410                evel_json_close_object(jbuf);
411             }
412             item_added2 = true;
413             jsobj_field_item = dlist_get_next(jsobj_field_item);
414         }
415         evel_json_close_list(jbuf);
416         if( !item_added2 )
417         {
418           evel_json_rewind(jbuf);
419         }
420        }
421
422     evel_enc_kv_string(jbuf, "objectName", jsonobjp->object_name);
423     evel_enc_kv_opt_string(jbuf, "objectSchema", &jsonobjp->objectschema);
424     evel_enc_kv_opt_string(jbuf, "objectSchemaUrl", &jsonobjp->objectschemaurl);
425     evel_enc_kv_opt_string(jbuf, "nfSubscribedObjectName", &jsonobjp->nfsubscribedobjname);
426     evel_enc_kv_opt_string(jbuf, "nfSubscriptionId", &jsonobjp->nfsubscriptionid);
427     evel_json_close_object(jbuf);
428     item_added = true;
429   }
430   other_field_item = dlist_get_next(other_field_item);
431   }
432   evel_json_close_list(jbuf);
433
434   if (!item_added)
435   {
436      evel_json_rewind(jbuf);
437   }
438
439   }
440
441   if( evel_json_open_opt_named_list(jbuf, "nameValuePairs"))
442   {
443   other_field_item = dlist_get_first(&event->namedvalues);
444   while (other_field_item != NULL)
445   {
446     other_field = (OTHER_FIELD *) other_field_item->item;
447     assert(other_field != NULL);
448
449     evel_json_open_object(jbuf);
450     evel_enc_kv_string(jbuf, "name", other_field->name);
451     evel_enc_kv_string(jbuf, "value", other_field->value);
452     evel_json_close_object(jbuf);
453     other_field_item = dlist_get_next(other_field_item);
454   }
455   }
456   evel_json_close_list(jbuf);
457
458   evel_enc_version(jbuf, "otherFieldsVersion", event->major_version,event->minor_version);
459
460   evel_json_close_object(jbuf);
461
462   EVEL_EXIT();
463 }
464
465 /**************************************************************************//**
466  * Free an Other.
467  *
468  * Free off the Other supplied.  Will free all the contained allocated memory.
469  *
470  * @note It does not free the Other itself, since that may be part of a
471  * larger structure.
472  *****************************************************************************/
473 void evel_free_other(EVENT_OTHER * event)
474 {
475   OTHER_FIELD * other_field = NULL;
476
477   EVEL_ENTER();
478
479   /***************************************************************************/
480   /* Check preconditions.  As an internal API we don't allow freeing NULL    */
481   /* events as we do on the public API.                                      */
482   /***************************************************************************/
483   assert(event != NULL);
484   assert(event->header.event_domain == EVEL_DOMAIN_OTHER);
485
486   /***************************************************************************/
487   /* Free all internal strings then the header itself.                       */
488   /***************************************************************************/
489   other_field = dlist_pop_last(&event->namedvalues);
490   while (other_field != NULL)
491   {
492     EVEL_DEBUG("Freeing Other Field (%s, %s)",
493                other_field->name,
494                other_field->value);
495     free(other_field->name);
496     free(other_field->value);
497     free(other_field);
498     other_field = dlist_pop_last(&event->namedvalues);
499   }
500   evel_free_header(&event->header);
501
502   EVEL_EXIT();
503 }