{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} -- | Parse TSN XML for the DTD "injuriesxml.dtd". Each document -- contains a root element \ that in turn contains zero or -- more \s. -- -- The listings will be mapped to a database table called "injuries" -- automatically. The root message is not retained. -- module TSN.XML.Injuries ( Listing, Message( listings ), injuries_tests ) where import Data.Tuple.Curry ( uncurryN ) import Database.Groundhog() import Database.Groundhog.TH ( defaultCodegenConfig, groundhog, mkPersist ) import Test.Tasty ( TestTree, testGroup ) import Test.Tasty.HUnit ( (@?=), testCase ) import Text.XML.HXT.Core ( PU, XmlPickler(..), xp4Tuple, xp6Tuple, xpElem, xpInt, xpList, xpPrim, xpText, xpWrap ) import TSN.DbImport ( DbImport(..), import_generic ) import Xml ( pickle_unpickle, unpickleable ) data Listing = Listing { team :: String, teamno :: Int, injuries :: String, updated :: Bool } deriving (Eq, Show) data Message = Message { xml_file_id :: Int, heading :: String, category :: String, sport :: String, listings :: [Listing], time_stamp :: String } deriving (Eq, Show) mkPersist defaultCodegenConfig [groundhog| - entity: Listing dbName: injuries |] pickle_listing :: PU Listing pickle_listing = xpElem "listing" $ xpWrap (from_tuple, to_tuple) $ xp4Tuple (xpElem "team" xpText) (xpElem "teamno" xpInt) (xpElem "injuries" xpText) (xpElem "updated" xpPrim) where from_tuple = uncurryN Listing to_tuple l = (team l, teamno l, injuries l, updated l) instance XmlPickler Listing where xpickle = pickle_listing pickle_message :: PU Message pickle_message = xpElem "message" $ xpWrap (from_tuple, to_tuple) $ xp6Tuple (xpElem "XML_File_ID" xpInt) (xpElem "heading" xpText) (xpElem "category" xpText) (xpElem "sport" xpText) (xpList pickle_listing) (xpElem "time_stamp" xpText) where from_tuple = uncurryN Message to_tuple m = (xml_file_id m, heading m, category m, sport m, listings m, time_stamp m) instance XmlPickler Message where xpickle = pickle_message instance DbImport Listing where dbimport = import_generic listings -- * Tasty Tests injuries_tests :: TestTree injuries_tests = testGroup "Injuries tests" [ test_pickle_of_unpickle_is_identity, test_unpickle_succeeds ] -- | Warning, succeess of this test does not mean that unpickling -- succeeded. test_pickle_of_unpickle_is_identity :: TestTree test_pickle_of_unpickle_is_identity = testCase "pickle composed with unpickle is the identity" $ do let path = "test/xml/injuriesxml.xml" (expected :: [Message], actual) <- pickle_unpickle "message" path actual @?= expected test_unpickle_succeeds :: TestTree test_unpickle_succeeds = testCase "unpickling succeeds" $ do let path = "test/xml/injuriesxml.xml" actual <- unpickleable path pickle_message let expected = True actual @?= expected