module DataFlow.JSONGraphFormat.Renderer (convertDiagram, renderJSONGraph) where
import qualified Data.Aeson as A
import Data.ByteString.Lazy (ByteString)
import Data.Text (pack, unpack)
import qualified Data.Map as M
import qualified Data.Vector as V
import DataFlow.Core
import qualified DataFlow.JSONGraphFormat as JG
getTitle :: JG.Metadata -> Maybe String
getTitle m = do
v <- M.lookup "title" m
case v of
(JG.Str s) -> Just s
_ -> Nothing
convertValue :: Value -> JG.Val
convertValue (String s) = JG.Str s
convertValue (Array vs) = JG.Arr (map convertValue vs)
convertAttrs :: Attributes -> M.Map String JG.Val
convertAttrs = M.map convertValue
withLabelAndMetadataFrom :: (Maybe String -> JG.Metadata -> v) -> JG.Metadata -> v
f `withLabelAndMetadataFrom` metadata = f (getTitle metadata) (M.delete "title" metadata)
addType :: String -> JG.Metadata -> JG.Metadata
addType s = M.insert "type" (JG.Str s)
addBoundary :: Maybe String -> JG.Metadata -> JG.Metadata
addBoundary (Just b) m = M.insert "trust-boundary" (JG.Str b) m
addBoundary Nothing m = m
convertNode :: Maybe String -> Node -> JG.Node
convertNode b (InputOutput id attrs) =
JG.Node id `withLabelAndMetadataFrom` addBoundary b (addType "io" $ convertAttrs attrs)
convertNode b (Function id attrs) =
JG.Node id `withLabelAndMetadataFrom` addBoundary b (addType "function" $ convertAttrs attrs)
convertNode b (Database id attrs) =
JG.Node id `withLabelAndMetadataFrom` addBoundary b (addType "database" $ convertAttrs attrs)
convertRootNode :: RootNode -> [JG.Node]
convertRootNode (Node node) = [convertNode Nothing node]
convertRootNode (TrustBoundary id' attrs nodes) =
map (convertNode (Just id')) nodes
convertFlow :: Flow -> JG.Edge
convertFlow (Flow source target attrs) =
JG.Edge source target `withLabelAndMetadataFrom` convertAttrs attrs
convertDiagram :: Diagram -> JG.Document
convertDiagram (Diagram attrs rootNodes flows) =
let nodes = concatMap convertRootNode rootNodes
edges = map convertFlow flows
graph = JG.Graph nodes edges `withLabelAndMetadataFrom` convertAttrs attrs
in JG.SingleGraph graph
renderJSONGraph :: Diagram -> ByteString
renderJSONGraph = A.encode . convertDiagram