This method binds the various model objects together in the correct hierarchy
        and adds referneces to this database object in the groups.

def _bind_model(self):
        """
        This method binds the various model objects together in the correct hierarchy
        and adds referneces to this database object in the groups.
        """

        if self.groups[0].level != 0:
            self.log.info("Got invalid first group: {0}".format(self.groups[0]))
            raise ValueError("Invalid group tree: first group must have level of 0 (got {0})".format(self.groups[0].level))
        
        # The KeePassX source code maintains that first group to have incremented 
        # level is a child of the previous group with a lower level.
        #
        # [R]
        #  | A (1)
        #  +-| B (2)
        #  | | C (2)
        #  | D (1)
        #  +-| E (2)
        #    | F (2)
        #    +-| G (3)
        #      | H (3)
        #      | I (3)
        #       
        
        class Stack(list):
            """ A class to make parsing code slightly more semantic. """
            def push(self, el):
                self.append(el)

        # This is a different parsing approach than taken by KeePassX (or other python               
        # libs), but seems a little more intuitive.  It could be further simplified
        # by noting that current_parent is always parent_stack[-1], but this is a bit
        # more readable.
        parent_stack = Stack([self.root])        
        current_parent = self.root
        prev_group = None
        for g in self.groups:
            g.db = self # Bind database to group objects
            if prev_group is not None: # first iteration is exceptional
                if g.level > prev_group.level: # Always true for iteration 1 since root has level of -1
                    # Dropping down a level; the previous group is the parent
                    current_parent = prev_group
                    parent_stack.push(current_parent)
                elif g.level < prev_group.level:
                    # Pop off parents until we have a parent with a level that is less than current
                    while g.level <= current_parent.level:
                        current_parent = parent_stack.pop()
                    parent_stack.push(current_parent) # We want to make sure that the top of the stack always matches current parent
                
            # bi-directional child-parent binding
            g.parent = current_parent
            current_parent.children.append(g)
            
            prev_group = g
            
        # Bind group objects to entries
        for entry in self.entries:
            for group in self.groups:
                if entry.group_id == group.id:
                    group.entries.append(entry)
                    entry.group = group
                    break
            else:
                # KeePassX adds these to the first group (i.e. root.children[0])
                raise NotImplementedError("Orphaned entries not (yet) supported.")