{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} module Codec.Xlsx.Types.Internal.CommentTable where import qualified Data.HashMap.Strict as HM import Data.List.Extra (nubOrd) import qualified Data.Map as Map import Data.Text (Text) import Data.Text.Lazy (toStrict) import qualified Data.Text.Lazy.Builder as B import qualified Data.Text.Lazy.Builder.Int as B import Safe import Text.XML import Text.XML.Cursor import Codec.Xlsx.Parser.Internal import Codec.Xlsx.Types.Comment import Codec.Xlsx.Types.Common import Codec.Xlsx.Writer.Internal newtype CommentTable = CommentTable { _commentsTable :: HM.HashMap CellRef Comment } deriving (Show, Eq) fromList :: [(CellRef, Comment)] -> CommentTable fromList = CommentTable . HM.fromList lookupComment :: CellRef -> CommentTable -> Maybe Comment lookupComment ref = HM.lookup ref . _commentsTable instance ToDocument CommentTable where toDocument = documentFromElement "Sheet comments generated by xlsx" . toElement "comments" instance ToElement CommentTable where toElement nm (CommentTable m) = Element { elementName = nm , elementAttributes = Map.empty , elementNodes = [ NodeElement $ elementListSimple "authors" authorNodes , NodeElement . elementListSimple "commentList" $ map commentToEl (HM.toList m) ] } where commentToEl (ref, Comment{..}) = Element { elementName = "comment" , elementAttributes = Map.fromList [ ("ref", ref) , ("authorId", lookupAuthor _commentAuthor)] , elementNodes = [NodeElement $ toElement "text" _commentText] } lookupAuthor a = fromJustNote "author lookup" $ HM.lookup a authorIds authorNames = nubOrd . map _commentAuthor $ HM.elems m decimalToText :: Integer -> Text decimalToText = toStrict . B.toLazyText . B.decimal authorIds = HM.fromList $ zip authorNames (map decimalToText [0..]) authorNodes = map (elementContent "author") authorNames instance FromCursor CommentTable where fromCursor cur = do let authorNames = cur $/ element (n"authors") &/ element (n"author") &/ content authors = HM.fromList $ zip [0..] authorNames items = cur $/ element (n"commentList") &/ element (n"comment") >=> parseComment authors return . CommentTable $ HM.fromList items parseComment :: HM.HashMap Int Text -> Cursor -> [(CellRef, Comment)] parseComment authors cur = do ref <- cur $| attribute "ref" txt <- cur $/ element (n"text") >=> fromCursor authorId <- cur $| attribute "authorId" >=> decimal let author = fromJustNote "authorId" $ HM.lookup authorId authors return (ref, Comment txt author)