93ae199e91706b0a556d7ae4ddafe436c43a7ca9
[sim/o1-interface.git] / ntsimulator / ntsim-ng / core / datastore / schema.c
1 /*************************************************************************
2 *
3 * Copyright 2020 highstreet technologies GmbH and others
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ***************************************************************************/
17
18 #define _GNU_SOURCE
19
20 #include "utils/log_utils.h"
21 #include "utils/type_utils.h"
22 #include <stdio.h>
23 #include <time.h>
24 #include <inttypes.h>
25 #include <assert.h>
26
27 #include <libyang/libyang.h>
28 #include "core/session.h"
29 #include "core/framework.h"
30
31 static int schema_print_recursive(struct lys_node *root);
32
33 int schema_get_xpaths(char ***root_xpath) {
34     assert_session();
35     assert(root_xpath);
36
37     const struct lys_module *module;
38     const struct lys_node *root;
39     uint32_t idx = 0;
40     char **list = 0;
41     int total = 0;
42
43     while((module = ly_ctx_get_module_iter(session_context, &idx)) != 0) {
44         if(!framework_is_populate_excluded_module(module->name) && (module->implemented)) {
45             LY_TREE_FOR(module->data, root) {
46                 if(((root->nodetype == LYS_CONTAINER) || (root->nodetype == LYS_LIST)) && ((root->flags & LYS_STATUS_DEPRC) == 0)) {
47                     list = (char **)realloc(list, sizeof(char *) * (total + 1));
48                     if(!list) {
49                         log_error("bad realloc");
50                         return NTS_ERR_FAILED;
51                     }
52                     asprintf(&list[total], "/%s:%s", module->name, root->name);
53                     if(!list[total]) {
54                         log_error("bad asprintf");
55                         return NTS_ERR_FAILED;
56                     }
57                     total++; 
58                 }
59                 else if(root->nodetype == LYS_USES) {
60                     struct lys_node *chd;
61                     LY_TREE_FOR(root->child, chd) {
62                         if(((chd->nodetype == LYS_CONTAINER) || (chd->nodetype == LYS_LIST)) && ((chd->flags & LYS_STATUS_DEPRC) == 0)) {
63                             list = (char **)realloc(list, sizeof(char *) * (total + 1));
64                             if(!list) {
65                                 log_error("bad realloc");
66                                 return NTS_ERR_FAILED;
67                             }
68                             asprintf(&list[total], "/%s:%s", module->name, chd->name);                            
69                             if(!list[total]) {
70                                 log_error("bad asprintf");
71                                 return NTS_ERR_FAILED;
72                             }
73                             total++;
74                         }
75                     }
76                 }
77             }
78         }
79     }
80
81     *root_xpath = list;
82     return total;
83 }
84
85 int schema_print_root_paths(void) {
86     assert_session();
87
88     struct lys_module *module;
89     struct lys_node *root;
90     uint32_t idx = 0;
91
92     while((module = (struct lys_module *)ly_ctx_get_module_iter(session_context, &idx)) != 0) {
93         log_message(2, "looking into module "LOG_COLOR_BOLD_MAGENTA"%s"LOG_COLOR_RESET"\n", module->name);
94
95         char flags[10];
96         strcpy(flags, "[     ]");
97         flags[1] = (module->implemented == 0) ? 'i' : ' ';
98         flags[3] = framework_is_populate_excluded_module(module->name) ? 'E' : ' ';
99
100         LY_TREE_FOR(module->data, root) {
101             log_message(2, "   found "LOG_COLOR_CYAN"%s"LOG_COLOR_RESET" with name "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET"\n", typeutils_yang_nodetype_to_str(root->nodetype), root->name);
102             if((root->nodetype == LYS_CONTAINER) || (root->nodetype == LYS_LIST)) {
103                 flags[2] = ((root->flags & LYS_STATUS_DEPRC) != 0) ? 'D' : ' ';
104                 flags[4] = ((root->flags & LYS_CONFIG_W) == 0) ? 'O' : 'R';
105                 flags[5] = (root->nodetype == LYS_CONTAINER) ? 'C' : 'L';
106                 log_message(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_CYAN" /%s:%s\n"LOG_COLOR_RESET, flags, module->name, root->name);
107             }
108             else if(root->nodetype == LYS_USES) {
109                 struct lys_node *chd;
110                 LY_TREE_FOR(root->child, chd) {
111                     log_message(2, "   - found "LOG_COLOR_CYAN"%s"LOG_COLOR_RESET" with name "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET"\n", typeutils_yang_nodetype_to_str(chd->nodetype), chd->name);
112                     if((chd->nodetype == LYS_CONTAINER) || (chd->nodetype == LYS_LIST)) {
113                         flags[2] = ((chd->flags & LYS_STATUS_DEPRC) != 0) ? 'D' : ' ';
114                         flags[4] = ((chd->flags & LYS_CONFIG_W) == 0) ? 'O' : 'R';
115                         flags[5] = (chd->nodetype == LYS_CONTAINER) ? 'C' : 'L';
116                         log_message(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_CYAN" /%s:%s\n"LOG_COLOR_RESET, flags, module->name, chd->name);
117                     }
118                 }
119             }
120         }
121     }
122
123     log_message(1, "\n   "LOG_COLOR_BOLD_YELLOW"i"LOG_COLOR_RESET" - not implemented | "LOG_COLOR_BOLD_YELLOW"D"LOG_COLOR_RESET" - deprecated | "LOG_COLOR_BOLD_YELLOW"E"LOG_COLOR_RESET" - excluded by config | "LOG_COLOR_BOLD_YELLOW"O"LOG_COLOR_RESET" - operational datastore | "LOG_COLOR_BOLD_YELLOW"R"LOG_COLOR_RESET" - running datastore | "LOG_COLOR_BOLD_YELLOW"C"LOG_COLOR_RESET" - container | "LOG_COLOR_BOLD_YELLOW"L"LOG_COLOR_RESET" - list\n\n");
124     return NTS_ERR_OK;
125 }
126
127 int schema_print_xpath(const char *xpath) {
128     assert_session();
129     assert(xpath);
130
131     if(xpath == 0) {
132         log_error("xpath is null");
133         return NTS_ERR_FAILED;
134     }
135     log_message(1, "printing out data structure for xpath: "LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET"\n", xpath);
136     
137     struct lys_node *elem = (struct lys_node *)ly_ctx_get_node(session_context, 0, xpath, 0);
138     if(elem == 0) {
139         log_error("ly_ctx_get_node failed for xpath: %s", xpath);
140         return NTS_ERR_FAILED;
141     }
142
143     struct lys_module *module = lys_node_module(elem);
144     if(module == 0) {
145         log_error("lys_node_module failed for xpath: %s", xpath);
146         return NTS_ERR_FAILED;
147     }
148
149
150     log_message(2, "module is %s @ revision %s\n", module->name, module->rev[0].date);
151
152     int rc = schema_print_recursive(elem);
153     if(rc != NTS_ERR_OK) {
154         log_error("schema_print_recursive failed for xpath: %s", xpath);
155         return NTS_ERR_FAILED;
156     }
157
158     log_message(1, "\n   "LOG_COLOR_BOLD_YELLOW"R"LOG_COLOR_RESET" - read only | "LOG_COLOR_BOLD_YELLOW"W"LOG_COLOR_RESET" - writeable | "LOG_COLOR_BOLD_YELLOW"*"LOG_COLOR_RESET" - key | "LOG_COLOR_BOLD_YELLOW"M"LOG_COLOR_RESET" - mandatory | "LOG_COLOR_BOLD_YELLOW"D"LOG_COLOR_RESET" - deprecated | "LOG_COLOR_BOLD_YELLOW"O"LOG_COLOR_RESET" - obsolete\n\n");
159     log_message(2, "schema_print() finished\n");
160
161     return NTS_ERR_OK;
162
163 }
164
165 static int schema_print_recursive(struct lys_node *root) {
166     assert(root);
167
168     char my_status[] = "[    ]";
169     my_status[1] = ((root->flags & LYS_CONFIG_W) == 0) ? 'R' : 'W';
170     my_status[2] = ((root->flags & LYS_MAND_TRUE) != 0) ? 'M' : ' ';
171     my_status[3] = ((root->flags & LYS_STATUS_DEPRC) != 0) ? 'D' : ' ';
172     my_status[4] = ((root->flags & LYS_STATUS_OBSLT) != 0) ? 'O' : ' ';
173
174     if(((root->parent) && (root->parent->nodetype == LYS_CASE)) && ((root->parent->flags & LYS_MAND_TRUE) != 0)) {
175         my_status[2] = 'M';
176     }
177
178     char *path = lys_data_path(root);
179     if((root->nodetype != LYS_CHOICE) && (root->nodetype != LYS_CASE)) {
180         log_message(1, LOG_COLOR_BOLD_YELLOW"%s"LOG_COLOR_RESET" %-100s ", my_status, path);
181
182         if(root->nodetype == LYS_LIST) {
183             struct lys_node_list *list = (struct lys_node_list *)root;
184             log_message(1, LOG_COLOR_CYAN"%s "LOG_COLOR_MAGENTA"(m: %d M: %d)"LOG_COLOR_RESET, 4 + typeutils_yang_nodetype_to_str(root->nodetype), list->min, list->max); //+4 to skip "LYS_"
185         }
186         else if(root->nodetype == LYS_LEAFLIST) {
187             struct lys_node_leaflist *list = (struct lys_node_leaflist *)root;
188             log_message(1, LOG_COLOR_CYAN"%s "LOG_COLOR_MAGENTA"(m: %d M: %d)"LOG_COLOR_RESET, 4 + typeutils_yang_nodetype_to_str(root->nodetype), list->min, list->max); //+4 to skip "LYS_"
189         }
190         else {
191             log_message(1, LOG_COLOR_CYAN"%-20s"LOG_COLOR_RESET, 4 + typeutils_yang_nodetype_to_str(root->nodetype)); //+4 to skip "LYS_"
192         }
193     }
194     free(path);
195
196     switch(root->nodetype) {
197         case LYS_LEAF:
198         case LYS_LEAFLIST: {            
199             struct lys_type *type = &((struct lys_node_leaf *)root)->type;
200             if(lys_is_key((const struct lys_node_leaf *)root, 0) != 0) {
201                 log_message(1, LOG_COLOR_BOLD_YELLOW"[*]"LOG_COLOR_RESET);
202             }
203             else {
204                 log_message(1, "   ");
205             }
206
207             char *typestr = typeutils_type_to_str(type);
208             log_message(1, "[%s]", typestr);
209             free(typestr);
210             
211             if(root->parent) {
212                 if(root->parent->nodetype == LYS_CASE) {
213                     log_message(1, " is a "LOG_COLOR_BLUE"CASE"LOG_COLOR_RESET" of "LOG_COLOR_CYAN"%s"LOG_COLOR_RESET, root->parent->parent->name);
214                 }
215             }
216             
217             if(type->base == LY_TYPE_LEAFREF) {
218                 log_message(1, " path: "LOG_COLOR_GREEN"%s"LOG_COLOR_RESET" ", type->info.lref.path);
219             }
220             else if(type->base == LY_TYPE_UNION) {
221                 if((type->info.uni.count == 0) && (type->der != 0)) {
222                     type = &type->der->type;
223                 }
224
225                 log_message(1, " available union types (%d):"LOG_COLOR_GREEN, type->info.uni.count);
226                 for(int i = 0; i < type->info.uni.count; i++) {
227                     char *typestr = typeutils_type_to_str(&type->info.uni.types[i]);
228                     log_message(1, " %s", typestr);
229                     free(typestr);
230                 }
231                 log_message(1, LOG_COLOR_RESET);
232             }
233         } break;
234
235         default:
236             break;
237     }
238   
239     if((root->nodetype != LYS_CHOICE) && (root->nodetype != LYS_CASE)) {
240         log_message(1, "\n");
241     }
242
243     struct lys_node *child = 0;
244     LY_TREE_FOR(root->child, child) {
245         int rc = schema_print_recursive(child);
246         if(rc != NTS_ERR_OK) {
247             return rc;
248         }
249     }
250
251     return NTS_ERR_OK;
252 }