def parse_grandchildren_of_class_with_obj(parent, child_class, obj,
    optional=True):
    """
    Find and parse all instances of the specified class contained by the child element with
    the tag name specified by the ``PARENT_TAG_NAME`` attribute of ``child_class``.
    
    :param parent: The parent ``Element`` object. 
    :param child_class: The class of the grandchildren.
    :param optional: If False, raise an exception if no parent node is found.
    
    :raises: An Exception if no parent node with the tag name specified by 
        ``child_class.PARENT_TAG_NAME`` is found and ``optional`` is ``False``.
    
    :returns: A list of objects of the type child_class.
    
    """
    node = parent.find(child_class.PARENT_TAG_NAME)
    if node == None:
        if optional:
            return []
        else:
            raise Exception(
                'Node {0} does not contain required child node {1}.'.format
                (parent.tag, child_class.TAG_NAME))
    else:
        nodes = node.findall(child_class.TAG_NAME)
        children = []
        for n in nodes:
            c = child_class.parse(n, obj)
            if c != None:
                children.append(c)
        return children
