]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/python/oils/utils/idl.py
parsing primary, sequence, and primitive settings from IDL
[Evergreen.git] / Open-ILS / src / python / oils / utils / idl.py
1 """
2 Parses an Evergreen fieldmapper IDL file and builds a global registry of
3 objects representing that IDL.
4
5 Typical usage:
6
7 >>> import osrf.system
8 >>> import oils.utils.idl
9 >>> osrf.system.connect('/openils/conf/opensrf_core.xml', 'config.opensrf')
10 >>> oils.utils.idl.oilsParseIDL()
11 >>> # 'bre' is a network registry hint, or class ID in the IDL file
12 ... print oils.utils.idl.oilsGetIDLParser().IDLObject['bre']['tablename']
13 biblio.record_entry
14 """
15 import osrf.net_obj
16 import osrf.log
17 import osrf.set
18
19 import sys, string, xml.dom.minidom
20 from oils.const import OILS_NS_OBJ, OILS_NS_PERSIST, OILS_NS_REPORTER
21
22 __global_parser = None
23
24 def oilsParseIDL():
25     global __global_parser
26     if __global_parser: return # no need to re-parse the IDL
27     idlParser = oilsIDLParser();
28     idlParser.setIDL(osrf.set.get('IDL'))
29     idlParser.parseIDL()
30     __global_parser = idlParser
31
32 def oilsGetIDLParser():
33     global __global_parser
34     return __global_parser
35
36 class oilsIDLParser(object):
37
38     def __init__(self):
39         self.IDLObject = {}
40
41     def setIDL(self, file):
42         osrf.log.log_info("setting IDL file to " + str(file))
43         self.idlFile = file
44
45     def __getAttr(self, node, name, ns=None):
46         """ Find the attribute value on a given node 
47             Namespace is ignored for now.. 
48             not sure if minidom has namespace support.
49             """
50         attr = node.attributes.get(name)
51         if attr:
52             return attr.nodeValue
53         return None
54
55     def parseIDL(self):
56         """Parses the IDL file and builds class objects"""
57
58         doc = xml.dom.minidom.parse(self.idlFile)
59         root = doc.childNodes[0]
60
61         for child in root.childNodes:
62         
63             if child.nodeType == child.ELEMENT_NODE:
64         
65                 # -----------------------------------------------------------------------
66                 # 'child' is the main class node for a fieldmapper class.
67                 # It has 'fields' and 'links' nodes as children.
68                 # -----------------------------------------------------------------------
69
70                 id = self.__getAttr(child, 'id')
71                 self.IDLObject[id] = {}
72                 obj = self.IDLObject[id]
73                 obj['fields'] = []
74
75                 obj['controller'] = self.__getAttr(child, 'controller')
76                 obj['fieldmapper'] = self.__getAttr(child, 'oils_obj:fieldmapper', OILS_NS_OBJ)
77                 obj['virtual'] = self.__getAttr(child, 'oils_persist:virtual', OILS_NS_PERSIST)
78                 obj['rpt_label'] = self.__getAttr(child, 'reporter:label', OILS_NS_REPORTER)
79                 obj['tablename'] = self.__getAttr(child, 'oils_persist:tablename', OILS_NS_REPORTER)
80
81                 keys = []
82                 for classNode in child.childNodes:
83                     if classNode.nodeType == classNode.ELEMENT_NODE:
84                         if classNode.nodeName == 'fields':
85                             keys = self.parseFields(id, classNode)
86
87                 osrf.net_obj.register_hint(id, keys, 'array')
88
89         doc.unlink()
90
91
92     def parseFields(self, cls, fields):
93         """Takes the fields node and parses the included field elements"""
94
95         keys = []
96         idlobj = self.IDLObject[cls]
97
98         idlobj['field_meta'] = {
99             'primary': self.__getAttr(fields, 'oils_persist:primary', OILS_NS_PERSIST),
100             'sequence': self.__getAttr(fields, 'oils_persist:sequence', OILS_NS_PERSIST)
101         }
102
103         for field in fields.childNodes:
104             if field.nodeType == field.ELEMENT_NODE:
105                 keys.append(None)
106         
107         for field in fields.childNodes:
108             obj = {}
109             if field.nodeType == fields.ELEMENT_NODE:
110                 name            = self.__getAttr(field, 'name')
111                 position        = int(self.__getAttr(field, 'oils_obj:array_position', OILS_NS_OBJ))
112                 obj['name'] = name
113
114                 try:
115                     keys[position] = name
116                 except Exception, e:
117                     osrf.log.log_error("parseFields(): position out of range.  pos=%d : key-size=%d" % (position, len(keys)))
118                     raise e
119
120                 virtual = self.__getAttr(field, 'oils_persist:virtual', OILS_NS_PERSIST)
121                 obj['rpt_label'] = self.__getAttr(field, 'reporter:label', OILS_NS_REPORTER)
122                 obj['rpt_dtype'] = self.__getAttr(field, 'reporter:datatype', OILS_NS_REPORTER)
123                 obj['rpt_select'] = self.__getAttr(field, 'reporter:selector', OILS_NS_REPORTER)
124                 obj['primitive'] = self.__getAttr(field, 'oils_persist:primitive', OILS_NS_PERSIST)
125
126                 if virtual == string.lower('true'):
127                     obj['virtual']  = True
128                 else:
129                     obj['virtual']  = False
130
131                 idlobj['fields'].append(obj)
132
133         return keys
134
135
136
137