B
    bq                 @   sD   d Z G dd deZG dd deZG dd dZG dd dZd	S )
aN  Linked list functionality for use in Bio.Nexus.

Provides functionality of a linked list.
Each node has one (or none) predecessor, and an arbitrary number of successors.
Nodes can store arbitrary data in a NodeData class.

Subclassed by Nexus.Trees to store phylogenetic trees.

Bug reports to Frank Kauff (fkauff@biologie.uni-kl.de)
c               @   s   e Zd ZdZdS )ChainExceptionz1Provision for the management of Chain exceptions.N)__name__
__module____qualname____doc__ r   r   .lib/python3.7/site-packages/Bio/Nexus/Nodes.pyr      s   r   c               @   s   e Zd ZdZdS )NodeExceptionz0Provision for the management of Node exceptions.N)r   r   r   r   r   r   r   r   r      s   r   c               @   sb   e Zd ZdZdd Zdd Zdd Zdd	d
Zdd Zdd Z	dd Z
dd Zdd Zdd ZdS )Chainz0Stores a list of nodes that are linked together.c             C   s   i | _ d| _dS )zInitialize a node chain.N)chainid)selfr   r   r   __init__#   s    zChain.__init__c             C   s   |  j d7  _ | j S )z/Get a new id for a node in the chain (PRIVATE).   )r   )r   r   r   r   _get_id(   s    zChain._get_idc             C   s   t | j S )zReturn a list of all node ids.)listr   keys)r   r   r   r   all_ids-   s    zChain.all_idsNc             C   sf   |dk	r$|| j kr$tdt| n>|  }|| || |dk	rX| j | | || j |< |S )zAttach node to another.NzUnknown predecessor: )r   r   strr   set_idset_prevadd_succ)r   nodeprevr   r   r   r   add1   s    


z	Chain.addc             C   s   || j krtdt| | j |  }| j | | | j |  }x|D ]}| j | | qLW | j | | | j | }| | |S )z=Delete node from chain and relinks successors to predecessor.zUnknown ID: )	r   r   r   get_prevremove_succget_succr   r   kill)r   r   prev_idZsucc_idsir   r   r   r   collapse>   s    



zChain.collapsec             C   s(   || j krtdt| n| j |= dS )z>Kill a node from chain without caring to what it is connected.zUnknown ID: N)r   r   r   )r   r   r   r   r   r   L   s    
z
Chain.killc             C   sd   || j krtdt| nD| j | j}|dk	rP| j | j| j | j| d| j | _|S dS )z%Disconnect node from his predecessor.zUnknown ID: N)r   r   r   r   succpopindex)r   r   r   r   r   r   unlinkS   s    
 zChain.unlinkc             C   sh   || j krtdt| nH|| j kr8tdt| n,| | | j | j| | j | | dS )zConnect son to parent.zUnknown ID: N)r   r   r   r%   r"   appendr   )r   parentZchildr   r   r   link^   s    


z
Chain.linkc             C   sN   ||ks|| j |  krdS x*| j |  D ]}| ||r.dS q.W dS dS )z+Check if grandchild is a subnode of parent.TFN)r   r   is_parent_of)r   r'   Z
grandchildsnr   r   r   r)   i   s    zChain.is_parent_ofc             C   sn   || j ks|| j krtd| ||r0||kr4g S x4| j |  D ]"}| ||rD|g| || S qDW dS )zQReturn a list of all node_ids between two nodes (excluding start, including end).zUnknown node.N)r   r   r)   r   trace)r   startZfinishr*   r   r   r   r+   t   s    zChain.trace)N)r   r   r   r   r   r   r   r   r!   r   r%   r(   r)   r+   r   r   r   r   r	       s   
r	   c               @   sj   e Zd ZdZdddZdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd ZdS )NodezA single node.Nc             C   s   d| _ || _d| _g | _dS )z>Represent a node with one predecessor and multiple successors.N)r   datar   r"   )r   r.   r   r   r   r      s    zNode.__init__c             C   s   | j dk	rtd|| _ dS )z%Set the id of a node, if not set yet.NzNode id cannot be changed.)r   r   )r   r   r   r   r   r      s    
zNode.set_idc             C   s   | j S )zReturn the node's id.)r   )r   r   r   r   get_id   s    zNode.get_idc             C   s   | j S )z'Return a list of the node's successors.)r"   )r   r   r   r   r      s    zNode.get_succc             C   s   | j S )z(Return the id of the node's predecessor.)r   )r   r   r   r   r      s    zNode.get_prevc             C   s,   t |tg r| j| n| j| dS )z'Add a node id to the node's successors.N)
isinstancetyper"   extendr&   )r   r   r   r   r   r      s    zNode.add_succc             C   s   | j | dS )z,Remove a node id from the node's successors.N)r"   remove)r   r   r   r   r   r      s    zNode.remove_succc             C   s    t |tg std|| _dS )zSet the node's successors.z$Node successor must be of list type.N)r0   r1   r   r"   )r   Znew_succr   r   r   set_succ   s    zNode.set_succc             C   s
   || _ dS )zSet the node's predecessor.N)r   )r   r   r   r   r   r      s    zNode.set_prevc             C   s   | j S )zReturn a node's data.)r.   )r   r   r   r   get_data   s    zNode.get_datac             C   s
   || _ dS )zSet a node's data.N)r.   )r   r.   r   r   r   set_data   s    zNode.set_data)N)r   r   r   r   r   r   r/   r   r   r   r   r4   r   r5   r6   r   r   r   r   r-      s   
r-   N)r   	Exceptionr   r   r	   r-   r   r   r   r   <module>   s   _