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