module NetSpider.SeqID
(
SeqIDMaker,
newSeqIDMaker,
convertGraph,
convertLink,
convertNode,
convertNodeID,
originalIDFor
) where
import Data.Foldable (foldl')
import Data.List (reverse)
import Data.Hashable (Hashable)
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HM
import NetSpider.Snapshot.Internal
( SnapshotNode(_nodeId),
SnapshotLink(_sourceNode, _destinationNode),
SnapshotGraph
)
data SeqIDMaker n i =
SeqIDMaker
{ toSeqID :: HashMap n i,
fromSeqID :: HashMap i n,
nextID :: i
}
deriving (Show,Eq)
newSeqIDMaker :: i
-> SeqIDMaker n i
newSeqIDMaker init_id = SeqIDMaker HM.empty HM.empty init_id
convertNodeID :: (Eq n, Hashable n, Enum i, Eq i, Hashable i)
=> SeqIDMaker n i
-> n
-> (SeqIDMaker n i, i)
convertNodeID maker nid =
case HM.lookup nid $ toSeqID maker of
Just existing_id -> (maker, existing_id)
Nothing -> (new_maker, new_id)
where
new_id = nextID maker
new_next_id = succ $ new_id
new_maker = maker { toSeqID = new_to,
fromSeqID = new_from,
nextID = new_next_id
}
new_to = HM.insert nid new_id $ toSeqID maker
new_from = HM.insert new_id nid $ fromSeqID maker
convertGraph :: (Eq n, Hashable n, Enum i, Eq i, Hashable i)
=> SeqIDMaker n i -> SnapshotGraph n na la -> (SeqIDMaker n i, SnapshotGraph i na la)
convertGraph maker (nodes, links) = (new_maker, (new_nodes, new_links))
where
(inter_maker, new_nodes_rev) = foldl' nodeFolder (maker, []) nodes
nodeFolder (m, ns) node = let (step_m, new_node) = convertNode m node
in (step_m, new_node : ns)
new_nodes = reverse new_nodes_rev
(new_maker, new_links_rev) = foldl' linkFolder (inter_maker, []) links
linkFolder (m, ls) link = let (step_m, new_link) = convertLink m link
in (step_m, new_link : ls)
new_links = reverse new_links_rev
convertLink :: (Eq n, Hashable n, Enum i, Eq i, Hashable i)
=> SeqIDMaker n i -> SnapshotLink n la -> (SeqIDMaker n i, SnapshotLink i la)
convertLink maker link = (new_maker, new_link)
where
(inter_maker, seq_source) = convertNodeID maker $ _sourceNode link
(new_maker, seq_dest) = convertNodeID inter_maker $ _destinationNode link
new_link = link { _sourceNode = seq_source, _destinationNode = seq_dest }
convertNode :: (Eq n, Hashable n, Enum i, Eq i, Hashable i)
=> SeqIDMaker n i -> SnapshotNode n na -> (SeqIDMaker n i, SnapshotNode i na)
convertNode maker node = (new_maker, new_node)
where
(new_maker, seq_id) = convertNodeID maker $ _nodeId node
new_node = node { _nodeId = seq_id }
originalIDFor :: (Eq i, Hashable i)
=> SeqIDMaker n i -> i -> Maybe n
originalIDFor maker seq_id = HM.lookup seq_id $ fromSeqID maker