[xml] refactor to use xml-conduit instead of xmlbf

parent 00dcba85
Pipeline #5380 failed with stages
in 5 minutes and 2 seconds
...@@ -12,7 +12,7 @@ STORE_DIR="${1:-$DEFAULT_STORE}" ...@@ -12,7 +12,7 @@ STORE_DIR="${1:-$DEFAULT_STORE}"
# `sha256sum` result calculated on the `cabal.project` and `cabal.project.freeze`. # `sha256sum` result calculated on the `cabal.project` and `cabal.project.freeze`.
# This ensures the files stay deterministic so that CI cache can kick in. # This ensures the files stay deterministic so that CI cache can kick in.
expected_cabal_project_hash="3c1002c8ed7be226b2e189fdb7debef5b3c43d0f56e44df73d500954074c4568" expected_cabal_project_hash="3c1002c8ed7be226b2e189fdb7debef5b3c43d0f56e44df73d500954074c4568"
expected_cabal_project_freeze_hash="2d3704d107bd8d08056ce4f0eb1f42202cb7f49a67c62a2445a6c70c7235f861" expected_cabal_project_freeze_hash="ee7ee880d93d58e52407e971033440291ddb20023a2e8090aa5b335ecbfbc649"
cabal --store-dir=$STORE_DIR v2-update 'hackage.haskell.org,2023-06-24T21:28:46Z' cabal --store-dir=$STORE_DIR v2-update 'hackage.haskell.org,2023-06-24T21:28:46Z'
......
...@@ -2177,7 +2177,6 @@ constraints: any.AC-Angle ==1.0, ...@@ -2177,7 +2177,6 @@ constraints: any.AC-Angle ==1.0,
any.servant-swagger ==1.1.10, any.servant-swagger ==1.1.10,
any.servant-swagger-ui ==0.3.5.4.5.0, any.servant-swagger-ui ==0.3.5.4.5.0,
any.servant-swagger-ui-core ==0.3.5, any.servant-swagger-ui-core ==0.3.5,
any.servant-xml ==1.0.1.4,
any.serverless-haskell ==0.12.6, any.serverless-haskell ==0.12.6,
any.serversession ==1.0.2, any.serversession ==1.0.2,
any.serversession-frontend-wai ==1.0, any.serversession-frontend-wai ==1.0,
...@@ -2734,8 +2733,6 @@ constraints: any.AC-Angle ==1.0, ...@@ -2734,8 +2733,6 @@ constraints: any.AC-Angle ==1.0,
any.xml-to-json ==2.0.1, any.xml-to-json ==2.0.1,
any.xml-to-json-fast ==2.0.0, any.xml-to-json-fast ==2.0.0,
any.xml-types ==0.3.8, any.xml-types ==0.3.8,
any.xmlbf ==0.6.1,
any.xmlbf-xeno ==0.2,
any.xmlgen ==0.6.2.2, any.xmlgen ==0.6.2.2,
any.xmonad ==0.15, any.xmonad ==0.15,
any.xmonad-contrib ==0.16, any.xmonad-contrib ==0.16,
......
...@@ -387,7 +387,7 @@ library ...@@ -387,7 +387,7 @@ library
RankNTypes RankNTypes
RecordWildCards RecordWildCards
StrictData StrictData
ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates -Wmissing-signatures -Wunused-binds -Wunused-imports -Werror -freduction-depth=300 -fplugin=Clippy ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates -Wmissing-signatures -Wunused-binds -Wunused-imports -Werror -freduction-depth=300 -fplugin=Clippy -fprint-potential-instances
if flag(test-crypto) if flag(test-crypto)
cpp-options: -DTEST_CRYPTO cpp-options: -DTEST_CRYPTO
build-depends: build-depends:
...@@ -530,7 +530,7 @@ library ...@@ -530,7 +530,7 @@ library
, servant-server ^>= 0.18.3 , servant-server ^>= 0.18.3
, servant-swagger ^>= 1.1.10 , servant-swagger ^>= 1.1.10
, servant-swagger-ui ^>= 0.3.5.3.5.0 , servant-swagger-ui ^>= 0.3.5.3.5.0
, servant-xml ^>= 1.0.1.4 , servant-xml-conduit == 0.1.0.4
, simple-reflect ^>= 0.3.3 , simple-reflect ^>= 0.3.3
, singletons ^>= 2.7 , singletons ^>= 2.7
, split ^>= 0.2.3.4 , split ^>= 0.2.3.4
...@@ -567,7 +567,6 @@ library ...@@ -567,7 +567,6 @@ library
, wreq ^>= 0.5.3.3 , wreq ^>= 0.5.3.3
, xml-conduit ^>= 1.9.1.3 , xml-conduit ^>= 1.9.1.3
, xml-types ^>= 0.3.8 , xml-types ^>= 0.3.8
, xmlbf ^>= 0.6.1
, yaml ^>= 0.11.8.0 , yaml ^>= 0.11.8.0
, zip ^>= 1.7.2 , zip ^>= 1.7.2
, zlib ^>= 0.6.2.3 , zlib ^>= 0.6.2.3
......
...@@ -48,7 +48,7 @@ import Gargantext.Prelude ...@@ -48,7 +48,7 @@ import Gargantext.Prelude
import Gargantext.Utils.Jobs (serveJobsAPI, MonadJobStatus(..)) import Gargantext.Utils.Jobs (serveJobsAPI, MonadJobStatus(..))
import Servant import Servant
import Servant.Job.Async (AsyncJobsAPI) import Servant.Job.Async (AsyncJobsAPI)
import Servant.XML import Servant.XML.Conduit (XML)
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- | There is no Delete specific API for Graph since it can be deleted -- | There is no Delete specific API for Graph since it can be deleted
......
...@@ -7,6 +7,10 @@ Maintainer : team@gargantext.org ...@@ -7,6 +7,10 @@ Maintainer : team@gargantext.org
Stability : experimental Stability : experimental
Portability : POSIX Portability : POSIX
See
https://martin.hoppenheit.info/blog/2023/xml-stream-processing-with-haskell/
for a tutorial of xml-conduit rendering.
-} -}
...@@ -19,87 +23,71 @@ module Gargantext.Core.Viz.Graph.GEXF ...@@ -19,87 +23,71 @@ module Gargantext.Core.Viz.Graph.GEXF
where where
import Conduit import Conduit
import Data.HashMap.Lazy qualified as HashMap import Data.Conduit.Combinators qualified as CC
import Data.XML.Types qualified as XML import Data.XML.Types qualified as XML
import Gargantext.Core.Viz.Graph.Types qualified as G import Gargantext.Core.Viz.Graph.Types qualified as G
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Prelude qualified as P
import Prelude qualified import Prelude qualified
-- import Text.XML qualified as XML import Servant (MimeRender(..), MimeUnrender(..))
import Servant.XML.Conduit (XML)
import Text.XML.Stream.Render qualified as XML import Text.XML.Stream.Render qualified as XML
import Xmlbf qualified as Xmlbf
-- Converts to GEXF format
-- See https://gephi.org/gexf/format/
graphToXML :: Monad m => G.Graph -> ConduitT i XML.Event m () graphToXML :: Monad m => G.Graph -> ConduitT i XML.Event m ()
graphToXML (G.Graph { .. }) = root _graph_nodes _graph_edges graphToXML (G.Graph { .. }) = root _graph_nodes _graph_edges
where where
-- root :: [G.Node] -> [G.Edge] -> ConduitT i XML.Event m () -- root :: [G.Node] -> [G.Edge] -> ConduitT i XML.Event m ()
root gn ge = root gn ge =
XML.tag "gexf" params $ meta .| (graph gn ge) XML.tag "gexf" params $ meta <> (graph gn ge)
where where
params = XML.attr "xmlns" "http://www.gexf.net/1.3" params = XML.attr "xmlns" "http://www.gexf.net/1.3"
<> XML.attr "xmlns:viz" "http://gexf.net/1.3/viz"
<> XML.attr "xmlns:xsi" "http://www.w3.org/2001/XMLSchema-instance"
<> XML.attr "xsi:schemaLocation" "http://gexf.net/1.3 http://gexf.net/1.3/gexf.xsd"
<> XML.attr "version" "1.3" <> XML.attr "version" "1.3"
meta = XML.tag "meta" params $ XML.content "x" meta = XML.tag "meta" params $ creator <> desc
where where
params = XML.attr "lastmodifieddate" "2020-03-13" params = XML.attr "lastmodifieddate" "2020-03-13"
creator = XML.tag "creator" mempty $ XML.content "Gargantext.org"
desc = XML.tag "description" mempty $ XML.content "Gargantext gexf file"
graph _gn _ge = XML.tag "graph" mempty $ XML.content "graph here" graph :: (Monad m) => [G.Node] -> [G.Edge] -> ConduitT i XML.Event m ()
graph gn ge = XML.tag "graph" params $ (nodes gn) <> (edges ge)
where
params = XML.attr "mode" "static"
<> XML.attr "defaultedgetype" "directed"
nodes :: (Monad m) => [G.Node] -> ConduitT i XML.Event m ()
nodes gn = XML.tag "nodes" mempty (yieldMany gn .| awaitForever node')
node' :: (Monad m) => G.Node -> ConduitT i XML.Event m ()
node' (G.Node { .. }) = XML.tag "node" params (XML.tag "viz:size" sizeParams $ XML.content "")
where
params = XML.attr "id" node_id
<> XML.attr "label" node_label
sizeParams = XML.attr "value" (show node_size)
-- Converts to GEXF format edges :: (Monad m) => [G.Edge] -> ConduitT i XML.Event m ()
-- See https://gephi.org/gexf/format/ edges ge = XML.tag "edges" mempty (yieldMany ge .| awaitForever edge')
instance Xmlbf.ToXml G.Graph where edge' :: (Monad m) => G.Edge -> ConduitT i XML.Event m ()
toXml (G.Graph { _graph_nodes = graphNodes edge' (G.Edge { .. }) = XML.tag "edge" params $ XML.content ""
, _graph_edges = graphEdges }) = root graphNodes graphEdges where
params = XML.attr "id" edge_id
<> XML.attr "source" edge_source
<> XML.attr "target" edge_target
<> XML.attr "weight" (show edge_weight)
instance MimeRender XML G.Graph where
mimeRender _ g = runConduitPure (source .| CC.sinkLazyBuilder)
where where
root :: [G.Node] -> [G.Edge] -> [Xmlbf.Node] namespaces = [ ("viz", "http://gexf.net/1.3/viz")
root gn ge = , ("xsi", "http://www.w3.org/2001/XMLSchema-instance")
Xmlbf.element "gexf" params $ meta <> (graph gn ge) , ("schemaLocation", "http://gexf.net/1.3") ]
where source = graphToXML g .| XML.renderBuilder (XML.def { XML.rsNamespaces = namespaces })
params = HashMap.fromList [ ("xmlns", "http://www.gexf.net/1.3") --encoded = source .| mapC TE.encodeUtf8
, ("xmlns:viz", "http://gexf.net/1.3/viz")
, ("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
, ("xsi:schemaLocation", "http://gexf.net/1.3 http://gexf.net/1.3/gexf.xsd")
, ("version", "1.3") ]
meta = Xmlbf.element "meta" params $ creator <> desc
where
params = HashMap.fromList [ ("lastmodifieddate", "2020-03-13") ]
creator = Xmlbf.element "creator" HashMap.empty $ Xmlbf.text "Gargantext.org"
desc = Xmlbf.element "description" HashMap.empty $ Xmlbf.text "Gargantext gexf file"
graph :: [G.Node] -> [G.Edge] -> [Xmlbf.Node]
graph gn ge = Xmlbf.element "graph" params $ (nodes gn) <> (edges ge)
where
params = HashMap.fromList [ ("mode", "static")
, ("defaultedgetype", "directed") ]
nodes :: [G.Node] -> [Xmlbf.Node]
nodes gn = Xmlbf.element "nodes" HashMap.empty $ P.concatMap node' gn
node' :: G.Node -> [Xmlbf.Node]
node' (G.Node { node_id = nId, node_label = l, node_size = w}) =
Xmlbf.element "node" params (Xmlbf.element "viz:size" sizeParams [])
where
params = HashMap.fromList [ ("id", nId)
, ("label", l) ]
sizeParams = HashMap.fromList [ ("value", show w) ]
edges :: [G.Edge] -> [Xmlbf.Node]
edges gn = Xmlbf.element "edges" HashMap.empty $ P.concatMap edge gn
edge :: G.Edge -> [Xmlbf.Node]
edge (G.Edge { edge_id = eId
, edge_source = es
, edge_target = et
, edge_weight = ew }) =
Xmlbf.element "edge" params []
where
params = HashMap.fromList [ ("id", eId)
, ("source", es)
, ("target", et)
, ("weight", show ew)]
-- just to be able to derive a client for the entire gargantext API, -- just to be able to derive a client for the entire gargantext API,
-- we however want to avoid sollicitating this instance -- we however want to avoid sollicitating this instance
instance Xmlbf.FromXml G.Graph where instance MimeUnrender XML G.Graph where
fromXml = Prelude.error "FromXml Graph: not defined, just a placeholder" mimeUnrender _ _ = Prelude.error "MimeUnrender Graph: not defined, just a placeholder"
...@@ -134,15 +134,12 @@ extra-deps: ...@@ -134,15 +134,12 @@ extra-deps:
- servant-ekg-0.3.1@sha256:19bd9dc3943983da8e79d6f607614c68faea4054fb889d508c8a2b67b6bdd448,2203 - servant-ekg-0.3.1@sha256:19bd9dc3943983da8e79d6f607614c68faea4054fb889d508c8a2b67b6bdd448,2203
- servant-flatten-0.2@sha256:276896f7c5cdec5b8f8493f6205fded0cc602d050b58fdb09a6d7c85c3bb0837,1234 - servant-flatten-0.2@sha256:276896f7c5cdec5b8f8493f6205fded0cc602d050b58fdb09a6d7c85c3bb0837,1234
- servant-mock-0.8.7@sha256:64cb3e52bbd51ab6cb25e3f412a99ea712c6c26f1efd117f01a8d1664df49c67,2306 - servant-mock-0.8.7@sha256:64cb3e52bbd51ab6cb25e3f412a99ea712c6c26f1efd117f01a8d1664df49c67,2306
- servant-xml-1.0.1.4@sha256:6c9f2986ac42e72fe24b794c660763a1966a18d696b34cd4f4ed15165edd4aa0,851
- stemmer-0.5.2@sha256:823aec56249ec2619f60a2c0d1384b732894dbbbe642856d337ebfe9629a0efd,4082 - stemmer-0.5.2@sha256:823aec56249ec2619f60a2c0d1384b732894dbbbe642856d337ebfe9629a0efd,4082
- taggy-0.2.1@sha256:7bc55ddba178971dc6052163597f0445a0a2b5b0ca0e84ce651d53d722e3c265,4662 - taggy-0.2.1@sha256:7bc55ddba178971dc6052163597f0445a0a2b5b0ca0e84ce651d53d722e3c265,4662
- taggy-lens-0.1.2@sha256:091ca81d02bd3d7fb493dce0148e1a38f25eb178a1ebd751043a23239e5e3265,3009 - taggy-lens-0.1.2@sha256:091ca81d02bd3d7fb493dce0148e1a38f25eb178a1ebd751043a23239e5e3265,3009
- tasty-hspec-1.2.0.3 - tasty-hspec-1.2.0.3
- tmp-postgres-1.34.1.0 - tmp-postgres-1.34.1.0
- vector-0.12.3.0@sha256:0ae2c1ba86f0077910be242ec6802cc3d7725fe7b2bea6987201aa3737b239b5,7953 - vector-0.12.3.0@sha256:0ae2c1ba86f0077910be242ec6802cc3d7725fe7b2bea6987201aa3737b239b5,7953
- xmlbf-0.6.1@sha256:57867fcb39e0514d17b3328ff5de8d241a18482fc89bb742d9ed820a6a2a5187,1540
- xmlbf-xeno-0.2@sha256:39f70fced6052524c290cf595f114661c721452e65fc3e0953a44e7682a6a6b0,950
# For the graph clustering # For the graph clustering
ghc-options: ghc-options:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment