# Path: props/graph_representation/node.py
# def isProp(node):
#     """
#     check if this node is a prop instance
#     
#     @type  node: Node
#     @param node: node to examine
#     
#     @rtype  bool
#     @return True iff this node is prop node instance
#     """
#     #TODO: efficiency
#     return isinstance(node,PropNode)
# 
# def isTime(node):
#     """
#     check if this node is a time instance
#     
#     @type  node: Node
#     @param node: node to examine
#     
#     @rtype  bool
#     @return True iff this node is time node instance
#     """
#     #TODO: efficiency
#     return isinstance(node,TimeNode)


from props.graph_representation.node import isProp, isTime

    class to bunch together all function of propagation on a digraph
    Mainly in order to store the graph as a member which all these functions can edit.   
    """
    def __init__(self,graph):
        self.gr = graph
        self.applyPropagation()
        
    def applyPropagation(self):
        """
        Apply closure propagation algorithms on the graph
        """
        change = True
        while change:
            change = self.propogateFeatures()
    
    def propogateFeatures(self):
        """
        handle propagating features between nodes of the graph
        
        @rtype  bool
        @return True iff this function has changed the graph in some way 
        """
        ret = False
        for curNode in self.gr.nodes():
            # for each node in the graph
            curNodeNeigbours = self.gr.neighbors(curNode)
            for curPropogateNode in curNode.propagateTo:
                # for each of its propgated nodes
                curPropogateNodeNeigboursIds = [cpn.uid for cpn in self.gr.neighbors(curPropogateNode)]
                for curNeigbour in curNodeNeigbours:

# Path: props/graph_representation/node.py
# def isProp(node):
#     """
#     check if this node is a prop instance
#     
#     @type  node: Node
#     @param node: node to examine
#     
#     @rtype  bool
#     @return True iff this node is prop node instance
#     """
#     #TODO: efficiency
#     return isinstance(node,PropNode)
# 
# def isTime(node):
#     """
#     check if this node is a time instance
#     
#     @type  node: Node
#     @param node: node to examine
#     
#     @rtype  bool
#     @return True iff this node is time node instance
#     """
#     #TODO: efficiency
#     return isinstance(node,TimeNode)


# Path: props/graph_representation/propagate.py
from props.graph_representation.node import isProp, isTime

    class to bunch together all function of propagation on a digraph
    Mainly in order to store the graph as a member which all these functions can edit.   
    """
    def __init__(self,graph):
        self.gr = graph
        self.applyPropagation()
        
    def applyPropagation(self):
        """
        Apply closure propagation algorithms on the graph
        """
        change = True
        while change:
            change = self.propogateFeatures()
    
    def propogateFeatures(self):
        """
        handle propagating features between nodes of the graph
        
        @rtype  bool
        @return True iff this function has changed the graph in some way 
        """
        ret = False
        for curNode in self.gr.nodes():
            # for each node in the graph
            curNodeNeigbours = self.gr.neighbors(curNode)
            for curPropogateNode in curNode.propagateTo:
                # for each of its propgated nodes
                curPropogateNodeNeigboursIds = [cpn.uid for cpn in self.gr.neighbors(curPropogateNode)]
                for curNeigbour in curNodeNeigbours:

                    if isProp(curNeigbour) or isTime(curNeigbour):
