[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)
-- Converts to GEXF format
-- See https://gephi.org/gexf/format/
instance Xmlbf.ToXml G.Graph where
toXml (G.Graph { _graph_nodes = graphNodes
, _graph_edges = graphEdges }) = root graphNodes graphEdges
where where
root :: [G.Node] -> [G.Edge] -> [Xmlbf.Node] params = XML.attr "mode" "static"
root gn ge = <> XML.attr "defaultedgetype" "directed"
Xmlbf.element "gexf" params $ meta <> (graph gn ge)
where nodes :: (Monad m) => [G.Node] -> ConduitT i XML.Event m ()
params = HashMap.fromList [ ("xmlns", "http://www.gexf.net/1.3") nodes gn = XML.tag "nodes" mempty (yieldMany gn .| awaitForever node')
, ("xmlns:viz", "http://gexf.net/1.3/viz") node' :: (Monad m) => G.Node -> ConduitT i XML.Event m ()
, ("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") node' (G.Node { .. }) = XML.tag "node" params (XML.tag "viz:size" sizeParams $ XML.content "")
, ("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 where
params = HashMap.fromList [ ("mode", "static") params = XML.attr "id" node_id
, ("defaultedgetype", "directed") ] <> XML.attr "label" node_label
nodes :: [G.Node] -> [Xmlbf.Node] sizeParams = XML.attr "value" (show node_size)
nodes gn = Xmlbf.element "nodes" HashMap.empty $ P.concatMap node' gn
edges :: (Monad m) => [G.Edge] -> ConduitT i XML.Event m ()
node' :: G.Node -> [Xmlbf.Node] edges ge = XML.tag "edges" mempty (yieldMany ge .| awaitForever edge')
node' (G.Node { node_id = nId, node_label = l, node_size = w}) = edge' :: (Monad m) => G.Edge -> ConduitT i XML.Event m ()
Xmlbf.element "node" params (Xmlbf.element "viz:size" sizeParams []) edge' (G.Edge { .. }) = XML.tag "edge" params $ XML.content ""
where where
params = HashMap.fromList [ ("id", nId) params = XML.attr "id" edge_id
, ("label", l) ] <> XML.attr "source" edge_source
sizeParams = HashMap.fromList [ ("value", show w) ] <> XML.attr "target" edge_target
edges :: [G.Edge] -> [Xmlbf.Node] <> XML.attr "weight" (show edge_weight)
edges gn = Xmlbf.element "edges" HashMap.empty $ P.concatMap edge gn
edge :: G.Edge -> [Xmlbf.Node]
edge (G.Edge { edge_id = eId instance MimeRender XML G.Graph where
, edge_source = es mimeRender _ g = runConduitPure (source .| CC.sinkLazyBuilder)
, edge_target = et
, edge_weight = ew }) =
Xmlbf.element "edge" params []
where where
params = HashMap.fromList [ ("id", eId) namespaces = [ ("viz", "http://gexf.net/1.3/viz")
, ("source", es) , ("xsi", "http://www.w3.org/2001/XMLSchema-instance")
, ("target", et) , ("schemaLocation", "http://gexf.net/1.3") ]
, ("weight", show ew)] source = graphToXML g .| XML.renderBuilder (XML.def { XML.rsNamespaces = namespaces })
--encoded = source .| mapC TE.encodeUtf8
-- 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