]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/c-apps/oils_idl-core.c
typo stopping "retrieve" methods from being generated
[Evergreen.git] / Open-ILS / src / c-apps / oils_idl-core.c
1 #include "openils/oils_idl.h"
2 /*
3  * vim:noet:ts=4:
4  */
5
6 #include <stdlib.h>
7 #include <string.h>
8 #include <libxml/globals.h>
9 #include <libxml/xmlerror.h>
10 #include <libxml/parser.h>
11 #include <libxml/tree.h>
12 #include <libxml/debugXML.h>
13 #include <libxml/xmlmemory.h>
14
15 #define PERSIST_NS "http://open-ils.org/spec/opensrf/IDL/persistence/v1"
16 #define OBJECT_NS "http://open-ils.org/spec/opensrf/IDL/objects/v1"
17 #define BASE_NS "http://opensrf.org/spec/IDL/base/v1"
18 #define REPORTER_NS "http://open-ils.org/spec/opensrf/IDL/reporter/v1"
19 #define PERM_NS "http://open-ils.org/spec/opensrf/IDL/permacrud/v1"
20
21 static xmlDocPtr idlDoc = NULL; // parse and store the IDL here
22
23 /* parse and store the IDL here */
24 static osrfHash* idlHash;
25
26 osrfHash* oilsIDL(void) { return idlHash; }
27 osrfHash* oilsIDLInit( const char* idl_filename ) {
28
29         if (idlHash) return idlHash;
30
31         char* string_tmp = NULL;
32
33         idlHash = osrfNewHash();
34         osrfHash* usrData = NULL;
35
36         osrfLogInfo(OSRF_LOG_MARK, "Parsing the IDL XML...");
37         idlDoc = xmlReadFile( idl_filename, NULL, XML_PARSE_XINCLUDE );
38         
39         if (!idlDoc) {
40                 osrfLogError(OSRF_LOG_MARK, "Could not load or parse the IDL XML file!");
41                 return NULL;
42         }
43
44         osrfLogDebug(OSRF_LOG_MARK, "Initializing the Fieldmapper IDL...");
45
46         xmlNodePtr docRoot = xmlDocGetRootElement(idlDoc);
47         xmlNodePtr kid = docRoot->children;
48         while (kid) {
49                 if (!strcmp( (char*)kid->name, "class" )) {
50
51                         usrData = osrfNewHash();
52                         osrfHashSet( usrData, xmlGetProp(kid, BAD_CAST "id"), "classname");
53                         osrfHashSet( usrData, xmlGetNsProp(kid, BAD_CAST "fieldmapper", BAD_CAST OBJECT_NS), "fieldmapper");
54                         osrfHashSet( usrData, xmlGetNsProp(kid, BAD_CAST "readonly", BAD_CAST PERSIST_NS), "readonly");
55
56                         osrfHashSet( idlHash, usrData, (char*)osrfHashGet(usrData, "classname") );
57
58                         string_tmp = NULL;
59                         if ((string_tmp = (char*)xmlGetNsProp(kid, BAD_CAST "tablename", BAD_CAST PERSIST_NS))) {
60                                 osrfLogDebug(OSRF_LOG_MARK, "Using table '%s' for class %s", string_tmp, osrfHashGet(usrData, "classname") );
61                                 osrfHashSet(
62                                         usrData,
63                                         strdup( string_tmp ),
64                                         "tablename"
65                                 );
66                         }
67
68                         string_tmp = NULL;
69                         if ((string_tmp = (char*)xmlGetNsProp(kid, BAD_CAST "virtual", BAD_CAST PERSIST_NS))) {
70                                 osrfHashSet(
71                                         usrData,
72                                         strdup( string_tmp ),
73                                         "virtual"
74                                 );
75                         }
76
77                         osrfStringArray* controller = osrfNewStringArray(0);
78                         string_tmp = NULL;
79                         if( (string_tmp = (char*)xmlGetProp(kid, BAD_CAST "controller") )) {
80                                 char* controller_list = strdup( string_tmp );
81                                 osrfLogDebug(OSRF_LOG_MARK, "Controller list is %s", string_tmp );
82
83                                 if (strlen( controller_list ) > 0) {
84                                         char* st_tmp = NULL;
85                                         char* _controller_class = strtok_r(controller_list, " ", &st_tmp);
86                                         osrfStringArrayAdd(controller, strdup(_controller_class));
87
88                                         while ((_controller_class = strtok_r(NULL, " ", &st_tmp))) {
89                                                 osrfStringArrayAdd(controller, strdup(_controller_class));
90                                         }
91                                 }
92                                 free(controller_list);
93                         }
94                         osrfHashSet( usrData, controller, "controller");
95
96
97                         osrfHash* _tmp;
98                         osrfHash* links = osrfNewHash();
99                         osrfHash* fields = osrfNewHash();
100                         osrfHash* pcrud = osrfNewHash();
101
102                         osrfHashSet( usrData, fields, "fields" );
103                         osrfHashSet( usrData, links, "links" );
104
105                         xmlNodePtr _cur = kid->children;
106
107                         while (_cur) {
108
109                                 if (!strcmp( (char*)_cur->name, "fields" )) {
110
111                                         string_tmp = NULL;
112                                         if( (string_tmp = (char*)xmlGetNsProp(_cur, BAD_CAST "primary", BAD_CAST PERSIST_NS)) ) {
113                                                 osrfHashSet(
114                                                         usrData,
115                                                         strdup( string_tmp ),
116                                                         "primarykey"
117                                                 );
118                                         }
119
120                                         string_tmp = NULL;
121                                         if( (string_tmp = (char*)xmlGetNsProp(_cur, BAD_CAST "sequence", BAD_CAST PERSIST_NS)) ) {
122                                                 osrfHashSet(
123                                                         usrData,
124                                                         strdup( string_tmp ),
125                                                         "sequence"
126                                                 );
127                                         }
128
129                                         xmlNodePtr _f = _cur->children;
130
131                                         while(_f) {
132                                                 if (strcmp( (char*)_f->name, "field" )) {
133                                                         _f = _f->next;
134                                                         continue;
135                                                 }
136
137                                                 _tmp = osrfNewHash();
138
139                                                 string_tmp = NULL;
140                                                 if( (string_tmp = (char*)xmlGetNsProp(_f, BAD_CAST "array_position", BAD_CAST OBJECT_NS)) ) {
141                                                         osrfHashSet(
142                                                                 _tmp,
143                                                                 strdup( string_tmp ),
144                                                                 "array_position"
145                                                         );
146                                                 }
147
148                                                 string_tmp = NULL;
149                                                 if( (string_tmp = (char*)xmlGetNsProp(_f, BAD_CAST "i18n", BAD_CAST PERSIST_NS)) ) {
150                                                         osrfHashSet(
151                                                                 _tmp,
152                                                                 strdup( string_tmp ),
153                                                                 "i18n"
154                                                         );
155                                                 }
156
157                                                 string_tmp = NULL;
158                                                 if( (string_tmp = (char*)xmlGetNsProp(_f, BAD_CAST "virtual", BAD_CAST PERSIST_NS)) ) {
159                                                         osrfHashSet(
160                                                                 _tmp,
161                                                                 strdup( string_tmp ),
162                                                                 "virtual"
163                                                         );
164                                                 }
165
166                                                 string_tmp = NULL;
167                                                 if( (string_tmp = (char*)xmlGetNsProp(_f, BAD_CAST "primitive", BAD_CAST PERSIST_NS)) ) {
168                                                         osrfHashSet(
169                                                                 _tmp,
170                                                                 strdup( string_tmp ),
171                                                                 "primitive"
172                                                         );
173                                                 }
174
175                                                 string_tmp = NULL;
176                                                 if( (string_tmp = (char*)xmlGetProp(_f, BAD_CAST "name")) ) {
177                                                         osrfHashSet(
178                                                                 _tmp,
179                                                                 strdup( string_tmp ),
180                                                                 "name"
181                                                         );
182                                                 }
183
184                                                 osrfLogDebug(OSRF_LOG_MARK, "Found field %s for class %s", string_tmp, osrfHashGet(usrData, "classname") );
185
186                                                 osrfHashSet(
187                                                         fields,
188                                                         _tmp,
189                                                         strdup( string_tmp )
190                                                 );
191                                                 _f = _f->next;
192                                         }
193                                 }
194
195                                 if (!strcmp( (char*)_cur->name, "links" )) {
196                                         xmlNodePtr _l = _cur->children;
197
198                                         while(_l) {
199                                                 if (strcmp( (char*)_l->name, "link" )) {
200                                                         _l = _l->next;
201                                                         continue;
202                                                 }
203
204                                                 _tmp = osrfNewHash();
205
206                                                 string_tmp = NULL;
207                                                 if( (string_tmp = (char*)xmlGetProp(_l, BAD_CAST "reltype")) ) {
208                                                         osrfHashSet(
209                                                                 _tmp,
210                                                                 strdup( string_tmp ),
211                                                                 "reltype"
212                                                         );
213                                                 }
214                                                 osrfLogDebug(OSRF_LOG_MARK, "Adding link with reltype %s", string_tmp );
215
216                                                 string_tmp = NULL;
217                                                 if( (string_tmp = (char*)xmlGetProp(_l, BAD_CAST "key")) ) {
218                                                         osrfHashSet(
219                                                                 _tmp,
220                                                                 strdup( string_tmp ),
221                                                                 "key"
222                                                         );
223                                                 }
224                                                 osrfLogDebug(OSRF_LOG_MARK, "Link fkey is %s", string_tmp );
225
226                                                 string_tmp = NULL;
227                                                 if( (string_tmp = (char*)xmlGetProp(_l, BAD_CAST "class")) ) {
228                                                         osrfHashSet(
229                                                                 _tmp,
230                                                                 strdup( string_tmp ),
231                                                                 "class"
232                                                         );
233                                                 }
234                                                 osrfLogDebug(OSRF_LOG_MARK, "Link fclass is %s", string_tmp );
235
236                                                 osrfStringArray* map = osrfNewStringArray(0);
237
238                                                 string_tmp = NULL;
239                                                 if( (string_tmp = (char*)xmlGetProp(_l, BAD_CAST "map") )) {
240                                                         char* map_list = strdup( string_tmp );
241                                                         osrfLogDebug(OSRF_LOG_MARK, "Link mapping list is %s", string_tmp );
242
243                                                         if (strlen( map_list ) > 0) {
244                                                                 char* st_tmp = NULL;
245                                                                 char* _map_class = strtok_r(map_list, " ", &st_tmp);
246                                                                 osrfStringArrayAdd(map, strdup(_map_class));
247                                                 
248                                                                 while ((_map_class = strtok_r(NULL, " ", &st_tmp))) {
249                                                                         osrfStringArrayAdd(map, strdup(_map_class));
250                                                                 }
251                                                         }
252                                                         free(map_list);
253                                                 }
254                                                 osrfHashSet( _tmp, map, "map");
255
256                                                 string_tmp = NULL;
257                                                 if( (string_tmp = (char*)xmlGetProp(_l, BAD_CAST "field")) ) {
258                                                         osrfHashSet(
259                                                                 _tmp,
260                                                                 strdup( string_tmp ),
261                                                                 "field"
262                                                         );
263                                                 }
264
265                                                 osrfHashSet(
266                                                         links,
267                                                         _tmp,
268                                                         strdup( string_tmp )
269                                                 );
270
271                                                 osrfLogDebug(OSRF_LOG_MARK, "Found link %s for class %s", string_tmp, osrfHashGet(usrData, "classname") );
272
273                                                 _l = _l->next;
274                                         }
275                                 }
276 /**** Structure of permacrud in memory ****
277
278 { create :
279     { permission : [ x, y, z ],
280       global_required : "true", -- anything else, or missing, is false
281       local_context : [ f1, f2 ],
282       foreign_context : { class1 : { fkey : local_class_key, field : class1_field, context : [ a, b, c ] }, ...}
283     },
284   retrieve : null, -- no perm check, or structure similar to the others
285   update : -- like create
286     ...
287   delete : -- like create
288     ...
289 }   
290
291 **** Structure of permacrud in memory ****/
292
293                                 if (!strcmp( (char*)_cur->name, "permacrud" )) {
294                                         osrfHashSet( usrData, pcrud, "permacrud" );
295                                         xmlNodePtr _l = _cur->children;
296
297                                         while(_l) {
298                                                 if (strcmp( (char*)_l->name, "actions" )) {
299                                                         _l = _l->next;
300                                                         continue;
301                                                 }
302
303                                                 xmlNodePtr _a = _l->children;
304
305                                                 while(_a) {
306                                                         if (
307                                                                 strcmp( (char*)_a->name, "create" ) &&
308                                                                 strcmp( (char*)_a->name, "retrieve" ) &&
309                                                                 strcmp( (char*)_a->name, "update" ) &&
310                                                                 strcmp( (char*)_a->name, "delete" )
311                                                         ) {
312                                                                 _a = _a->next;
313                                                                 continue;
314                                                         }
315
316                                                         string_tmp = strdup( (char*)_a->name );
317                                                         osrfLogDebug(OSRF_LOG_MARK, "Found Permacrud action %s for class %s", string_tmp, osrfHashGet(usrData, "classname") );
318
319                                                         _tmp = osrfNewHash();
320                                                         osrfHashSet( pcrud, _tmp, string_tmp );
321
322                                                         osrfStringArray* map = osrfNewStringArray(0);
323                                                         string_tmp = NULL;
324                                                         if( (string_tmp = (char*)xmlGetProp(_l, BAD_CAST "permission") )) {
325                                                                 char* map_list = strdup( string_tmp );
326                                                                 osrfLogDebug(OSRF_LOG_MARK, "Permacrud permission list is %s", string_tmp );
327         
328                                                                 if (strlen( map_list ) > 0) {
329                                                                         char* st_tmp = NULL;
330                                                                         char* _map_class = strtok_r(map_list, "|", &st_tmp);
331                                                                         osrfStringArrayAdd(map, strdup(_map_class));
332                                                         
333                                                                         while ((_map_class = strtok_r(NULL, "|", &st_tmp))) {
334                                                                                 osrfStringArrayAdd(map, strdup(_map_class));
335                                                                         }
336                                                                 }
337                                                                 free(map_list);
338                                                         }
339                                                         osrfHashSet( _tmp, map, "permission");
340
341                                                 osrfHashSet( _tmp, (char*)xmlGetProp(_l, BAD_CAST "global_required"), "global_required");
342
343                                                         map = osrfNewStringArray(0);
344                                                         string_tmp = NULL;
345                                                         if( (string_tmp = (char*)xmlGetProp(_l, BAD_CAST "context_field") )) {
346                                                                 char* map_list = strdup( string_tmp );
347                                                                 osrfLogDebug(OSRF_LOG_MARK, "Permacrud context_field list is %s", string_tmp );
348         
349                                                                 if (strlen( map_list ) > 0) {
350                                                                         char* st_tmp = NULL;
351                                                                         char* _map_class = strtok_r(map_list, "|", &st_tmp);
352                                                                         osrfStringArrayAdd(map, strdup(_map_class));
353                                                         
354                                                                         while ((_map_class = strtok_r(NULL, "|", &st_tmp))) {
355                                                                                 osrfStringArrayAdd(map, strdup(_map_class));
356                                                                         }
357                                                                 }
358                                                                 free(map_list);
359                                                         }
360                                                         osrfHashSet( _tmp, map, "local_context");
361
362                                                         osrfHash* foreign_context = osrfNewHash();
363                                                         osrfHashSet( _tmp, foreign_context, "foreign_context");
364
365                                                         xmlNodePtr _f = _l->children;
366
367                                                         while(_f) {
368                                                                 if ( strcmp( (char*)_f->name, "context" ) ) {
369                                                                         _f = _f->next;
370                                                                         continue;
371                                                                 }
372
373                                                                 string_tmp = NULL;
374                                                                 if( (string_tmp = (char*)xmlGetProp(_f, BAD_CAST "link")) ) {
375                                                                         osrfLogDebug(OSRF_LOG_MARK, "Permacrud context link definition is %s", string_tmp );
376
377                                                                         osrfHash* _flink = oilsIDLFindPath("/%s/links/%s", osrfHashGet(usrData, "classname"), string_tmp);
378
379                                                                         osrfHashSet( foreign_context, osrfNewHash(), osrfHashGet(_flink, "class") );
380                                                                         osrfHash* _tmp_fcontext = osrfHashGet( foreign_context, osrfHashGet(_flink, "class") );
381
382                                                                         osrfHashSet( _tmp_fcontext, osrfHashGet(_flink, "field"), "fkey" );
383                                                                         osrfHashSet( _tmp_fcontext, osrfHashGet(_flink, "key"), "field" );
384
385                                                                         map = osrfNewStringArray(0);
386                                                                         string_tmp = NULL;
387                                                                         if( (string_tmp = (char*)xmlGetProp(_f, BAD_CAST "field") )) {
388                                                                                 char* map_list = strdup( string_tmp );
389                                                                                 osrfLogDebug(OSRF_LOG_MARK, "Permacrud foreign context field list is %s", string_tmp );
390                         
391                                                                                 if (strlen( map_list ) > 0) {
392                                                                                         char* st_tmp = NULL;
393                                                                                         char* _map_class = strtok_r(map_list, "|", &st_tmp);
394                                                                                         osrfStringArrayAdd(map, strdup(_map_class));
395                                                                         
396                                                                                         while ((_map_class = strtok_r(NULL, "|", &st_tmp))) {
397                                                                                                 osrfStringArrayAdd(map, strdup(_map_class));
398                                                                                         }
399                                                                                 }
400                                                                                 free(map_list);
401                                                                         }
402                                                                         osrfHashSet( _tmp_fcontext, map, "context");
403
404                                                                 } else {
405
406                                                                         if( (string_tmp = (char*)xmlGetProp(_f, BAD_CAST "field") )) {
407                                                                                 char* map_list = strdup( string_tmp );
408                                                                                 osrfLogDebug(OSRF_LOG_MARK, "Permacrud foreign context field list is %s", string_tmp );
409                         
410                                                                                 if (strlen( map_list ) > 0) {
411                                                                                         char* st_tmp = NULL;
412                                                                                         char* _map_class = strtok_r(map_list, "|", &st_tmp);
413                                                                                         osrfStringArrayAdd(osrfHashGet( _tmp, "local_context"), strdup(_map_class));
414                                                                         
415                                                                                         while ((_map_class = strtok_r(NULL, "|", &st_tmp))) {
416                                                                                                 osrfStringArrayAdd(osrfHashGet( _tmp, "local_context"), strdup(_map_class));
417                                                                                         }
418                                                                                 }
419                                                                                 free(map_list);
420                                                                         }
421
422                                                                 }
423                                                                 _f = _f->next;
424                                                         }
425                                                         _a = _a->next;
426                                                 }
427                                                 _l = _l->next;
428                                         }
429                                 }
430
431                                 if (!strcmp( (char*)_cur->name, "source_definition" )) {
432                                         string_tmp = NULL;
433                                         if( (string_tmp = (char*)xmlNodeGetContent(_cur)) ) {
434                                                 osrfLogDebug(OSRF_LOG_MARK, "Using source definition '%s' for class %s", string_tmp, osrfHashGet(usrData, "classname") );
435                                                 osrfHashSet(
436                                                         usrData,
437                                                         strdup( string_tmp ),
438                                                         "source_definition"
439                                                 );
440                                         }
441
442                                 }
443
444                                 _cur = _cur->next;
445                         } // end while
446                 }
447
448                 kid = kid->next;
449         } // end while
450
451         osrfLogInfo(OSRF_LOG_MARK, "...IDL XML parsed");
452
453         return idlHash;
454 }
455
456 osrfHash* oilsIDLFindPath( const char* path, ... ) {
457         if(!path || strlen(path) < 1) return NULL;
458
459         osrfHash* obj = idlHash;
460
461         VA_LIST_TO_STRING(path);
462         char* buf = VA_BUF;
463
464         char* token = NULL;
465         char* t = buf;
466         char* tt;
467
468         token = strtok_r(t, "/", &tt);
469         if(!token) return NULL;
470
471         do {
472                 obj = osrfHashGet(obj, token);
473         } while( (token = strtok_r(NULL, "/", &tt)) && obj);
474
475         return obj;
476 }
477
478 int oilsIDL_classIsFieldmapper ( const char* classname ) {
479         if (!classname) return 0;
480         if(oilsIDLFindPath( "/%s", classname )) return 1;
481         return 0;
482 }
483
484 int oilsIDL_ntop (const char* classname, const char* fieldname) {
485         osrfHash* _pos = NULL;
486
487         if (!oilsIDL_classIsFieldmapper(classname)) return -1;
488         _pos = oilsIDLFindPath( "/%s/fields/%s", classname, fieldname );
489         if (_pos) return atoi( osrfHashGet(_pos, "array_position") );
490         return -1;
491 }
492
493 char * oilsIDL_pton (const char* classname, int pos) {
494         char* ret = NULL;
495         osrfHash* f = NULL;
496         osrfHash* fields = NULL;
497         osrfHashIterator* itr = NULL;
498
499         if (!oilsIDL_classIsFieldmapper(classname)) return NULL;
500
501         fields = oilsIDLFindPath( "/%s/fields", classname );
502         itr = osrfNewHashIterator( fields );
503
504         while ( (f = osrfHashIteratorNext( itr )) ) {
505                 if ( atoi(osrfHashGet(f, "array_position")) == pos ) {
506                         ret = strdup(osrfHashIteratorKey(itr));
507                         break;
508                 }
509         }
510
511         osrfHashIteratorFree( itr );
512
513         return ret;
514 }
515