1 #include "openils/oils_idl.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>
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"
21 static xmlDocPtr idlDoc = NULL; // parse and store the IDL here
23 /* parse and store the IDL here */
24 static osrfHash* idlHash;
26 osrfHash* oilsIDL(void) { return idlHash; }
27 osrfHash* oilsIDLInit( const char* idl_filename ) {
29 if (idlHash) return idlHash;
31 char* string_tmp = NULL;
33 idlHash = osrfNewHash();
34 osrfHash* usrData = NULL;
36 osrfLogInfo(OSRF_LOG_MARK, "Parsing the IDL XML...");
37 idlDoc = xmlReadFile( idl_filename, NULL, XML_PARSE_XINCLUDE );
40 osrfLogError(OSRF_LOG_MARK, "Could not load or parse the IDL XML file!");
44 osrfLogDebug(OSRF_LOG_MARK, "Initializing the Fieldmapper IDL...");
46 xmlNodePtr docRoot = xmlDocGetRootElement(idlDoc);
47 xmlNodePtr kid = docRoot->children;
49 if (!strcmp( (char*)kid->name, "class" )) {
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");
56 osrfHashSet( idlHash, usrData, (char*)osrfHashGet(usrData, "classname") );
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") );
69 if ((string_tmp = (char*)xmlGetNsProp(kid, BAD_CAST "virtual", BAD_CAST PERSIST_NS))) {
77 osrfStringArray* controller = osrfNewStringArray(0);
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 );
83 if (strlen( controller_list ) > 0) {
85 char* _controller_class = strtok_r(controller_list, " ", &st_tmp);
86 osrfStringArrayAdd(controller, strdup(_controller_class));
88 while ((_controller_class = strtok_r(NULL, " ", &st_tmp))) {
89 osrfStringArrayAdd(controller, strdup(_controller_class));
92 free(controller_list);
94 osrfHashSet( usrData, controller, "controller");
98 osrfHash* links = osrfNewHash();
99 osrfHash* fields = osrfNewHash();
100 osrfHash* pcrud = osrfNewHash();
102 osrfHashSet( usrData, fields, "fields" );
103 osrfHashSet( usrData, links, "links" );
105 xmlNodePtr _cur = kid->children;
109 if (!strcmp( (char*)_cur->name, "fields" )) {
112 if( (string_tmp = (char*)xmlGetNsProp(_cur, BAD_CAST "primary", BAD_CAST PERSIST_NS)) ) {
115 strdup( string_tmp ),
121 if( (string_tmp = (char*)xmlGetNsProp(_cur, BAD_CAST "sequence", BAD_CAST PERSIST_NS)) ) {
124 strdup( string_tmp ),
129 xmlNodePtr _f = _cur->children;
132 if (strcmp( (char*)_f->name, "field" )) {
137 _tmp = osrfNewHash();
140 if( (string_tmp = (char*)xmlGetNsProp(_f, BAD_CAST "array_position", BAD_CAST OBJECT_NS)) ) {
143 strdup( string_tmp ),
149 if( (string_tmp = (char*)xmlGetNsProp(_f, BAD_CAST "i18n", BAD_CAST PERSIST_NS)) ) {
152 strdup( string_tmp ),
158 if( (string_tmp = (char*)xmlGetNsProp(_f, BAD_CAST "virtual", BAD_CAST PERSIST_NS)) ) {
161 strdup( string_tmp ),
167 if( (string_tmp = (char*)xmlGetNsProp(_f, BAD_CAST "primitive", BAD_CAST PERSIST_NS)) ) {
170 strdup( string_tmp ),
176 if( (string_tmp = (char*)xmlGetProp(_f, BAD_CAST "name")) ) {
179 strdup( string_tmp ),
184 osrfLogDebug(OSRF_LOG_MARK, "Found field %s for class %s", string_tmp, osrfHashGet(usrData, "classname") );
195 if (!strcmp( (char*)_cur->name, "links" )) {
196 xmlNodePtr _l = _cur->children;
199 if (strcmp( (char*)_l->name, "link" )) {
204 _tmp = osrfNewHash();
207 if( (string_tmp = (char*)xmlGetProp(_l, BAD_CAST "reltype")) ) {
210 strdup( string_tmp ),
214 osrfLogDebug(OSRF_LOG_MARK, "Adding link with reltype %s", string_tmp );
217 if( (string_tmp = (char*)xmlGetProp(_l, BAD_CAST "key")) ) {
220 strdup( string_tmp ),
224 osrfLogDebug(OSRF_LOG_MARK, "Link fkey is %s", string_tmp );
227 if( (string_tmp = (char*)xmlGetProp(_l, BAD_CAST "class")) ) {
230 strdup( string_tmp ),
234 osrfLogDebug(OSRF_LOG_MARK, "Link fclass is %s", string_tmp );
236 osrfStringArray* map = osrfNewStringArray(0);
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 );
243 if (strlen( map_list ) > 0) {
245 char* _map_class = strtok_r(map_list, " ", &st_tmp);
246 osrfStringArrayAdd(map, strdup(_map_class));
248 while ((_map_class = strtok_r(NULL, " ", &st_tmp))) {
249 osrfStringArrayAdd(map, strdup(_map_class));
254 osrfHashSet( _tmp, map, "map");
257 if( (string_tmp = (char*)xmlGetProp(_l, BAD_CAST "field")) ) {
260 strdup( string_tmp ),
271 osrfLogDebug(OSRF_LOG_MARK, "Found link %s for class %s", string_tmp, osrfHashGet(usrData, "classname") );
276 /**** Structure of permacrud in memory ****
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 ] }, ...}
284 retrieve : null, -- no perm check, or structure similar to the others
285 update : -- like create
287 delete : -- like create
291 **** Structure of permacrud in memory ****/
293 if (!strcmp( (char*)_cur->name, "permacrud" )) {
294 osrfHashSet( usrData, pcrud, "permacrud" );
295 xmlNodePtr _l = _cur->children;
298 if (strcmp( (char*)_l->name, "actions" )) {
303 xmlNodePtr _a = _l->children;
307 strcmp( (char*)_a->name, "create" ) &&
308 strcmp( (char*)_a->name, "retrieve" ) &&
309 strcmp( (char*)_a->name, "update" ) &&
310 strcmp( (char*)_a->name, "delete" )
316 string_tmp = strdup( (char*)_a->name );
317 osrfLogDebug(OSRF_LOG_MARK, "Found Permacrud action %s for class %s", string_tmp, osrfHashGet(usrData, "classname") );
319 _tmp = osrfNewHash();
320 osrfHashSet( pcrud, _tmp, string_tmp );
322 osrfStringArray* map = osrfNewStringArray(0);
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 );
328 if (strlen( map_list ) > 0) {
330 char* _map_class = strtok_r(map_list, "|", &st_tmp);
331 osrfStringArrayAdd(map, strdup(_map_class));
333 while ((_map_class = strtok_r(NULL, "|", &st_tmp))) {
334 osrfStringArrayAdd(map, strdup(_map_class));
339 osrfHashSet( _tmp, map, "permission");
341 osrfHashSet( _tmp, (char*)xmlGetProp(_l, BAD_CAST "global_required"), "global_required");
343 map = osrfNewStringArray(0);
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 );
349 if (strlen( map_list ) > 0) {
351 char* _map_class = strtok_r(map_list, "|", &st_tmp);
352 osrfStringArrayAdd(map, strdup(_map_class));
354 while ((_map_class = strtok_r(NULL, "|", &st_tmp))) {
355 osrfStringArrayAdd(map, strdup(_map_class));
360 osrfHashSet( _tmp, map, "local_context");
362 osrfHash* foreign_context = osrfNewHash();
363 osrfHashSet( _tmp, foreign_context, "foreign_context");
365 xmlNodePtr _f = _l->children;
368 if ( strcmp( (char*)_f->name, "context" ) ) {
374 if( (string_tmp = (char*)xmlGetProp(_f, BAD_CAST "link")) ) {
375 osrfLogDebug(OSRF_LOG_MARK, "Permacrud context link definition is %s", string_tmp );
377 osrfHash* _flink = oilsIDLFindPath("/%s/links/%s", osrfHashGet(usrData, "classname"), string_tmp);
379 osrfHashSet( foreign_context, osrfNewHash(), osrfHashGet(_flink, "class") );
380 osrfHash* _tmp_fcontext = osrfHashGet( foreign_context, osrfHashGet(_flink, "class") );
382 osrfHashSet( _tmp_fcontext, osrfHashGet(_flink, "field"), "fkey" );
383 osrfHashSet( _tmp_fcontext, osrfHashGet(_flink, "key"), "field" );
385 map = osrfNewStringArray(0);
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 );
391 if (strlen( map_list ) > 0) {
393 char* _map_class = strtok_r(map_list, "|", &st_tmp);
394 osrfStringArrayAdd(map, strdup(_map_class));
396 while ((_map_class = strtok_r(NULL, "|", &st_tmp))) {
397 osrfStringArrayAdd(map, strdup(_map_class));
402 osrfHashSet( _tmp_fcontext, map, "context");
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 );
410 if (strlen( map_list ) > 0) {
412 char* _map_class = strtok_r(map_list, "|", &st_tmp);
413 osrfStringArrayAdd(osrfHashGet( _tmp, "local_context"), strdup(_map_class));
415 while ((_map_class = strtok_r(NULL, "|", &st_tmp))) {
416 osrfStringArrayAdd(osrfHashGet( _tmp, "local_context"), strdup(_map_class));
431 if (!strcmp( (char*)_cur->name, "source_definition" )) {
433 if( (string_tmp = (char*)xmlNodeGetContent(_cur)) ) {
434 osrfLogDebug(OSRF_LOG_MARK, "Using source definition '%s' for class %s", string_tmp, osrfHashGet(usrData, "classname") );
437 strdup( string_tmp ),
451 osrfLogInfo(OSRF_LOG_MARK, "...IDL XML parsed");
456 osrfHash* oilsIDLFindPath( const char* path, ... ) {
457 if(!path || strlen(path) < 1) return NULL;
459 osrfHash* obj = idlHash;
461 VA_LIST_TO_STRING(path);
468 token = strtok_r(t, "/", &tt);
469 if(!token) return NULL;
472 obj = osrfHashGet(obj, token);
473 } while( (token = strtok_r(NULL, "/", &tt)) && obj);
478 int oilsIDL_classIsFieldmapper ( const char* classname ) {
479 if (!classname) return 0;
480 if(oilsIDLFindPath( "/%s", classname )) return 1;
484 int oilsIDL_ntop (const char* classname, const char* fieldname) {
485 osrfHash* _pos = NULL;
487 if (!oilsIDL_classIsFieldmapper(classname)) return -1;
488 _pos = oilsIDLFindPath( "/%s/fields/%s", classname, fieldname );
489 if (_pos) return atoi( osrfHashGet(_pos, "array_position") );
493 char * oilsIDL_pton (const char* classname, int pos) {
496 osrfHash* fields = NULL;
497 osrfHashIterator* itr = NULL;
499 if (!oilsIDL_classIsFieldmapper(classname)) return NULL;
501 fields = oilsIDLFindPath( "/%s/fields", classname );
502 itr = osrfNewHashIterator( fields );
504 while ( (f = osrfHashIteratorNext( itr )) ) {
505 if ( atoi(osrfHashGet(f, "array_position")) == pos ) {
506 ret = strdup(osrfHashIteratorKey(itr));
511 osrfHashIteratorFree( itr );