Hi everyone, <div><br></div><div><br></div><div>Following is the code i am reading, i don't see anywhere the declaration of Message.root object, </div><div>Where is it from?</div><div><br></div><div><div>#bots-modules</div>
<div>import bots.botslib as botslib</div><div>import bots.node as node</div><div>from bots.botsconfig import *</div><div><br></div><div><br></div><div>class Message(object):</div><div>    ''' abstract class; represents a edi message.</div>
<div>        is subclassed as outmessage or inmessage object.</div><div>    '''</div><div>    def __init__(self):</div><div>        self.recordnumber=0                #segment counter. Is not used for UNT of SE record; some editypes want sequential recordnumbering</div>
<div>        </div><div>    @staticmethod</div><div>    def display(records):</div><div>        '''for debugging lexed records.'''</div><div>        for record in records:</div><div>            t = 0</div>
<div>            for veld in record:</div><div>                if t==0:</div><div>                    print '%s    (Record-id)'%(veld[VALUE])</div><div>                else:</div><div>                    if veld[SFIELD]:</div>
<div>                        print '        %s    (sub)'%(veld[VALUE])</div><div>                    else:</div><div>                        print '    %s    (veld)'%(veld[VALUE])</div><div>                t += 1</div>
<div><br></div><div>    def get(self,*mpaths):</div><div>        ''' query tree (self.root) with mpath; get value (string); get None if not found.'''</div><div>        if self.root.record is None:</div>
<div>            raise botslib.MpathRootError('get("%s"): "root" of incoming message is empty; either split messages or use inn.getloop'%(str(mpaths)))</div><div>        return self.root.get(*mpaths)</div>
<div><br></div><div>    def getnozero(self,*mpaths):</div><div>        ''' like get, returns None is value is zero (0) or not numeric.</div><div>            Is sometimes usefull in mapping.'''</div>
<div>        if self.root.record is None:</div><div>            raise botslib.MpathRootError('get("%s"): "root" of incoming message is empty; either split messages or use inn.getloop'%(str(mpaths)))</div>
<div>        return self.root.getnozero(*mpaths)</div><div><br></div><div>    def getindicator(self,ind,*mpaths):</div><div>        ''' like get, returns None is value is zero (0) or not numeric.</div><div>            Is sometimes usefull in mapping.'''</div>
<div>        if self.root.record is None:</div><div>            raise botslib.MpathRootError('get("%s"): "root" of incoming message is empty; either split messages or use inn.getloop'%(str(mpaths)))</div>
<div>        return self.root.getindicator(ind,*mpaths)</div><div><br></div><div>    def getcount(self):</div><div>        ''' count number of nodes in self.root. Number of nodes is number of records.'''</div>
<div>        return self.root.getcount()</div><div><br></div><div>    def getcountoccurrences(self,*mpaths):</div><div>        ''' count number of nodes in self.root. Number of nodes is number of records.'''</div>
<div>        count = 0 </div><div>        for value in self.getloop(*mpaths):</div><div>            count += 1</div><div>        return count</div><div><br></div><div>    def getcountsum(self,*mpaths):</div><div>        ''' return the sum for all values found in mpath. Eg total number of ordered quantities.'''</div>
<div>        if self.root.record is None:</div><div>            raise botslib.MpathRootError('get("%s"): "root" of incoming message is empty; either split messages or use inn.getloop'%(str(mpaths)))</div>
<div>        return self.root.getcountsum(*mpaths)</div><div><br></div><div>    def getloop(self,*mpaths):</div><div>        ''' query tree with mpath; generates all the nodes. Is typically used as: for record in inn.get(mpath): </div>
<div>        '''</div><div>        if self.root.record:    #self.root is a real root</div><div>            for terug in self.root.getloop(*mpaths): #search recursive for rest of mpaths</div><div>                yield terug</div>
<div>        else:   #self.root is dummy root</div><div>            for childnode in self.root.children:</div><div>                for terug in childnode.getloop(*mpaths): #search recursive for rest of mpaths</div><div>                    yield terug</div>
<div><br></div><div>    def put(self,*mpaths):</div><div>        if self.root.record is None and self.root.children:</div><div>            raise botslib.MpathRootError('put("%s"): "root" of outgoing message is empty; use out.putloop'%(str(mpaths)))</div>
<div>        return self.root.put(*mpaths)</div><div><br></div><div>    def putloop(self,*mpaths):</div><div>        if not self.root.record:    #no input yet, and start with a putloop(): dummy root</div><div>            if len(mpaths) == 1:</div>
<div>                self.root.append(node.Node(mpaths[0]))</div><div>                return self.root.children[-1]</div><div>            else: #TODO: what if self.root.record is None and len(mpaths) > 1?</div><div>                raise botslib.MpathRootError('putloop("%s"): mpath too long???'%(str(mpaths)))</div>
<div>        return self.root.putloop(*mpaths)</div><div><br></div><div>    def sort(self,*mpaths):</div><div>        if self.root.record is None:</div><div>            raise botslib.MpathRootError('get("%s"): "root" of message is empty; either split messages or use inn.getloop'%(str(mpaths)))</div>
<div>        self.root.sort(*mpaths)</div><div>        </div><div>    def normalisetree(self,node):</div><div>        ''' The node tree is check, sorted, fields are formated etc.</div><div>            Always use this method before writing output.</div>
<div>        '''</div><div>        #~ node.display()</div><div>        #~ print 'normalisetree'</div><div>        self._checktree(node,self.defmessage.structure[0])</div><div>        self._canonicaltree(node,self.defmessage.structure[0])</div>
<div>        </div><div>    def _checktree(self,tree,structure):</div><div>        ''' checks tree with table:</div><div>            -   all records should be in table at the right place in hierarchy</div><div>
            -   for each record, all fields should be in grammar</div><div>            This function checks the root of grammar-structure with root of node tree</div><div>        '''</div><div>        if tree.record['BOTSID'] == structure[ID]:</div>
<div>            #check tree recursively with structure</div><div>            self._checktreecore(tree,structure)  </div><div>        else:</div><div>            raise botslib.MessageError('(Root)record %s of %s not in table %s'%(tree.record['BOTSID'],tree.record,self.defmessage.grammarname))</div>
<div>            </div><div>    def _checktreecore(self,node,structure):</div><div>        ''' recursive</div><div>        '''</div><div>        deletelist=[]</div><div>        self._checkfields(node.record,structure)</div>
<div>        if node.children and not LEVEL in structure:</div><div>            if self.ta_info['checkunknownentities']:</div><div>                raise botslib.MessageError('Record "%s" in message has children, but structure of grammar "%s" not. Found gg "%s".'%(node.record['BOTSID'],self.defmessage.grammarname,node.children[0].record['BOTSID']))</div>
<div>            node.children=[]</div><div>            return</div><div>        for childnode in node.children:          #for every node:</div><div>            for structure_record in structure[LEVEL]:           #search in grammar-records</div>
<div>                if childnode.record['BOTSID'] == structure_record[ID]:   #if found right structure_record</div><div>                    #check children recursive</div><div>                    self._checktreecore(childnode,structure_record)</div>
<div>                    break    #check next mpathnode</div><div>            else:   #checked all structure_record in grammar, but nothing found</div><div>                if self.ta_info['checkunknownentities']:</div>
<div>                    raise botslib.MessageError('Record "%s" in message not in structure of grammar "%s". Whole record: "%s".'%(childnode.record['BOTSID'],self.defmessage.grammarname,childnode.record))</div>
<div>                deletelist.append(childnode)</div><div>        for child in deletelist:</div><div>            node.children.remove(child)</div><div>                </div><div><br></div><div>    def _checkfields(self,record,structure_record):</div>
<div>        ''' checks for every field in record if field exists in structure_record (from grammar).</div><div>        '''</div><div>        deletelist=[]</div><div>        for field in record.keys():          #all fields in record should exist in structure_record</div>
<div>            for grammarfield in structure_record[FIELDS]:</div><div>                if grammarfield[ISFIELD]:    #if field (no composite)</div><div>                    if field == grammarfield[ID]:</div><div>                        break</div>
<div>                else:   #if composite</div><div>                    for grammarsubfield in grammarfield[SUBFIELDS]:   #loop subfields</div><div>                        if field == grammarsubfield[ID]:</div><div>                            break</div>
<div>                    else:</div><div>                        continue</div><div>                    break</div><div>            else:</div><div>                if self.ta_info['checkunknownentities']:</div><div>
                    raise botslib.MessageError('Field "%s" does not exist in record: %s'%(field,structure_record[MPATH]))</div><div>                    #~ raise botslib.MessageError('Field "%s" does not exist in record: %s'%(field,structure_record[ID]))       #alt voor MPATH</div>
<div>                    #~ raise botslib.MessageError('Field "%s" does not exist in record: %s'%(field,structure_record[FIELDS]))   #folder, text is too long</div><div>                deletelist.append(field)</div>
<div>        for field in deletelist:</div><div>            del record[field]</div><div>                </div><div>    def _canonicaltree(self,node,structure,headerrecordnumber=0):</div><div>        ''' For nodes: check min and max occurence; sort the nodes conform grammar</div>
<div>            For fields: check M/C; format the fields.</div><div>        '''</div><div>        sortednodelist = []</div><div>        self._canonicalfields(node.record,structure,headerrecordnumber)    #write the fields</div>
<div>        if LEVEL in structure:</div><div>            for structure_record in structure[LEVEL]:  #for structure_record of this level in grammar</div><div>                count = 0                           #count number of occurences of record</div>
<div>                for childnode in node.children:            #for every node in mpathtree; SPEED: delete nodes from list when found</div><div>                    if childnode.record['BOTSID'] != structure_record[ID]:   #if it is not the right NODE":</div>
<div>                        continue</div><div>                    count += 1</div><div>                    self._canonicaltree(childnode,structure_record,self.recordnumber)         #use rest of index in deeper level</div>
<div>                    sortednodelist.append(childnode)</div><div>                if structure_record[MIN] > count:</div><div>                    raise botslib.MessageError('Record "%s": mandatory but not present.'%(structure_record[MPATH]))</div>
<div>                if structure_record[MAX] < count:</div><div>                    raise botslib.MessageError('Record "%s": occures to often (%s times).'%(structure_record[MPATH],count))</div><div>            node.children=sortednodelist</div>
<div>            if hasattr(self,'do_queries'):</div><div>                self.do_queries(node,structure)</div><div><br></div><div>    def _canonicalfields(self,noderecord,structure_record,headerrecordnumber):</div>
<div>        ''' For fields: check M/C; format the fields. Field are not sorted here (a dict can not be sorted)</div><div>        '''</div><div>        #~ print noderecord</div><div>        for grammarfield in structure_record[FIELDS]:</div>
<div>            if grammarfield[ISFIELD]:    #if field (no composite)</div><div>                value = noderecord.get(grammarfield[ID],'')</div><div>                #~ print 'check field',grammarfield,value</div>
<div>                if not value:</div><div>                    if grammarfield[MANDATORY] == 'M':</div><div>                        raise botslib.MessageError('Record "%s": mandatory field "%s" not filled.'%(structure_record[MPATH],grammarfield[ID]))</div>
<div>                    elif not grammarfield[MINLENGTH]:   #if minlength=0</div><div>                        continue</div><div>                noderecord[grammarfield[ID]] = self._formatfield(value,grammarfield,structure_record)</div>
<div>            else:               #if composite</div><div>                compositefilled = False</div><div>                for grammarsubfield in grammarfield[SUBFIELDS]:   #loop subfields to see if one of them is there</div>
<div>                    if noderecord.get(grammarsubfield[ID],''):</div><div>                        compositefilled = True</div><div>                if not compositefilled:</div><div>                    if grammarfield[MANDATORY]=='M':</div>
<div>                        raise botslib.MessageError('Record "%s": mandatory composite "%s" not filled.'%(structure_record[MPATH],grammarfield[ID]))</div><div>                    continue</div>
<div>                for grammarsubfield in grammarfield[SUBFIELDS]:   #loop subfields</div><div>                    value = noderecord.get(grammarsubfield[ID],'')</div><div>                    #~ print 'check subfield',grammarsubfield,value</div>
<div>                    if not value:</div><div>                        if grammarsubfield[MANDATORY]=='M':</div><div>                            #~ print 'Record "%s": mandatory subfield "%s" not filled: "%s".'%(structure_record[MPATH],grammarsubfield[ID],noderecord)</div>
<div>                            raise botslib.MessageError('Record "%s": mandatory subfield "%s" not filled: "%s".'%(structure_record[MPATH],grammarsubfield[ID],noderecord))</div><div>
                        else:</div><div>                            continue</div><div>                    noderecord[grammarsubfield[ID]] = self._formatfield(value,grammarsubfield,structure_record)</div><div>                    #~ print 'fill',grammarfield[ID]</div>
<div><br></div><div>Thanks in advance.</div><div><br></div><div>Jim </div></div>