2 Parses an Evergreen fieldmapper IDL file and builds a global registry of
3 objects representing that IDL.
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
16 import osrf.log, osrf.set, osrf.ex
18 import sys, string, xml.dom.minidom
19 from oils.const import OILS_NS_OBJ, OILS_NS_PERSIST, OILS_NS_REPORTER
21 __global_parser = None
24 global __global_parser
25 if __global_parser: return # no need to re-parse the IDL
26 idlParser = oilsIDLParser();
27 idlParser.setIDL(osrf.set.get('IDL'))
29 __global_parser = idlParser
31 def oilsGetIDLParser():
32 global __global_parser
33 return __global_parser
35 class oilsIDLParser(object):
40 def setIDL(self, file):
41 osrf.log.log_info("setting IDL file to " + str(file))
44 def __getAttr(self, node, name, ns=None):
45 """ Find the attribute value on a given node
46 Namespace is ignored for now..
47 not sure if minidom has namespace support.
49 attr = node.attributes.get(name)
55 """Parses the IDL file and builds class objects"""
57 doc = xml.dom.minidom.parse(self.idlFile)
58 root = doc.childNodes[0]
60 for child in root.childNodes:
62 if child.nodeType == child.ELEMENT_NODE:
64 # -----------------------------------------------------------------------
65 # 'child' is the main class node for a fieldmapper class.
66 # It has 'fields' and 'links' nodes as children.
67 # -----------------------------------------------------------------------
70 self.__getAttr(child, 'id'),
71 controller = self.__getAttr(child, 'controller'),
72 fieldmapper = self.__getAttr(child, 'oils_obj:fieldmapper', OILS_NS_OBJ),
73 virtual = self.__getAttr(child, 'oils_persist:virtual', OILS_NS_PERSIST),
74 label = self.__getAttr(child, 'reporter:label', OILS_NS_REPORTER),
75 tablename = self.__getAttr(child, 'oils_persist:tablename', OILS_NS_REPORTER),
79 self.IDLObject[obj.name] = obj
81 fields = [f for f in child.childNodes if f.nodeName == 'fields']
82 links = [f for f in child.childNodes if f.nodeName == 'links']
83 keys = self.parseFields(obj, fields[0])
85 self.parse_links(obj, links[0])
87 osrf.net_obj.register_hint(obj.name, keys, 'array')
92 def parse_links(self, idlobj, links):
94 for link in [l for l in links.childNodes if l.nodeName == 'link']:
96 field = idlobj.get_field(self.__getAttr(link, 'field')),
97 rel_type = self.__getAttr(link, 'rel_type'),
98 key = self.__getAttr(link, 'key'),
99 map = self.__getAttr(link, 'map')
101 idlobj.links.append(obj)
104 def parseFields(self, idlobj, fields):
105 """Takes the fields node and parses the included field elements"""
109 idlobj.primary = self.__getAttr(fields, 'oils_persist:primary', OILS_NS_PERSIST)
110 idlobj.sequence = self.__getAttr(fields, 'oils_persist:sequence', OILS_NS_PERSIST)
112 # pre-flesh the array of keys to accomodate random index insertions
113 for field in fields.childNodes:
114 if field.nodeType == field.ELEMENT_NODE:
117 for field in [l for l in fields.childNodes if l.nodeName == 'field']:
121 name = self.__getAttr(field, 'name'),
122 position = int(self.__getAttr(field, 'oils_obj:array_position', OILS_NS_OBJ)),
123 virtual = self.__getAttr(field, 'oils_persist:virtual', OILS_NS_PERSIST),
124 label = self.__getAttr(field, 'reporter:label', OILS_NS_REPORTER),
125 rpt_datatype = self.__getAttr(field, 'reporter:datatype', OILS_NS_REPORTER),
126 rpt_select = self.__getAttr(field, 'reporter:selector', OILS_NS_REPORTER),
127 primitive = self.__getAttr(field, 'oils_persist:primitive', OILS_NS_PERSIST)
131 keys[obj.position] = obj.name
133 osrf.log.log_error("parseFields(): position out of range. pos=%d : key-size=%d" % (obj.position, len(keys)))
136 idlobj.fields.append(obj)
141 class IDLException(osrf.ex.OSRFException):
144 class IDLClass(object):
145 def __init__(self, name, **kwargs):
147 self.controller = kwargs.get('controller')
148 self.fieldmapper = kwargs.get('fieldmapper')
149 self.virtual = kwargs.get('virtual')
150 self.label = kwargs.get('label')
151 self.tablename = kwargs.get('tablename')
152 self.primary = kwargs.get('primary')
153 self.sequence = kwargs.get('sequence')
157 if self.virtual and self.virtual.lower() == 'true':
162 def get_field(self, field_name):
164 return [f for f in self.fields if f.name == field_name][0]
166 msg = "No field '%s' in IDL class '%s'" % (field_name, self.name)
167 osrf.log.log_error(msg)
168 #raise IDLException(msg)
170 class IDLField(object):
171 def __init__(self, idl_class, **kwargs):
173 @param idl_class The IDLClass object which owns this field
175 self.idl_class = idl_class
176 self.name = kwargs.get('name')
177 self.label = kwargs.get('label')
178 self.rpt_datatype = kwargs.get('rpt_datatype')
179 self.rpt_select = kwargs.get('rpt_select')
180 self.primitive = kwargs.get('primitive')
181 self.virtual = kwargs.get('virtual')
182 self.position = kwargs.get('position')
184 if self.virtual and self.virtual.lower() == 'true':
190 class IDLLink(object):
191 def __init__(self, field, **kwargs):
193 @param field The IDLField object this link references
196 self.rel_type = kwargs.get('rel_type')
197 self.key = kwargs.get('key')
198 self.map = kwargs.get('map')