-- Copyright (C) 2016-2017 Red Hat, Inc. -- -- This library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public -- License as published by the Free Software Foundation; either -- version 2.1 of the License, or (at your option) any later version. -- -- This library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with this library; if not, see . {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} module BDCS.Import.Comps(CompsPkg(..), CompsGroup(..), loadFromURI) where import Control.Monad.Reader(ReaderT) import Data.Conduit((.|), runConduitRes) import Data.Maybe(mapMaybe) import qualified Data.Text as T import Network.URI(URI(..)) import Text.XML(Document, sinkDoc) import Text.XML.Cursor import Text.XML.Stream.Parse(def) import BDCS.Import.Conduit(getFromURI, ungzipIfCompressed) import BDCS.Import.State(ImportState) data CompsPkg = CPMandatory T.Text | CPDefault T.Text | CPOptional T.Text | CPUnknown T.Text | T.Text `CPRequires` T.Text deriving(Show) data CompsGroup = CompsGroup T.Text T.Text [CompsPkg] deriving(Show) parseCompsPkg :: Cursor -> [CompsPkg] parseCompsPkg cursor = do let tys = cursor $| attribute "type" let names = cursor $/ content let reqs = cursor $| attribute' "requires" map toCompsPkg (zip3 tys names reqs) where -- Like attribute, but returns an empty string instead of an empty list. This is so tys, -- names, and reqs above are all the same length and the tuples line up. attribute' n c = case attribute n c of [] -> [""] x -> x toCompsPkg ("mandatory", n, _) = CPMandatory n toCompsPkg ("default", n, _) = CPDefault n toCompsPkg ("optional", n, _) = CPOptional n toCompsPkg ("conditional", n, "") = CPUnknown n toCompsPkg ("conditional", n, r) = n `CPRequires` r -- Shouldn't happen, but this marks them so we'll know there's something to look into. toCompsPkg (_, n, _) = CPUnknown n parseCompsGroup :: Cursor -> Maybe CompsGroup parseCompsGroup cursor = let groupIds = cursor $/ laxElement "id" &/ content groupNames = cursor $/ laxElement "name" &/ content packages = cursor $// laxElement "packagereq" >=> parseCompsPkg in case (groupIds, groupNames) of (fstId:_, fstName:_) -> Just $ CompsGroup fstId fstName packages _ -> Nothing extractGroups :: Document -> [CompsGroup] extractGroups doc = let cursor = fromDocument doc groupCursors = cursor $// laxElement "group" in mapMaybe parseCompsGroup groupCursors loadFromURI :: URI -> ReaderT ImportState IO () loadFromURI uri = do _groups <- extractGroups <$> runConduitRes (readMetadataPipeline uri) -- FIXME: For now we don't actually do any loading. There's a lot of questions -- about how this is going to fit into the database, but I want to make sure this -- code doesn't get lost. return () where readMetadataPipeline p = getFromURI p .| ungzipIfCompressed .| sinkDoc def