repo-based-blog-0.0.1: library/Web/RBB/Crawler/MetaCombiner.hs
{-# LANGUAGE TemplateHaskell #-}
{- |
Module : Web.RBB.Crawler.MetaCombiner
Description : Contract a list of meta data into a single value type
Copyright : (c) Sebastian Witte
License : BSD3
Maintainer : woozletoff@gmail.com
Stability : experimental
-}
module Web.RBB.Crawler.MetaCombiner
where
import Control.Lens hiding (Context)
import Control.Monad.State
import Data.IxSet hiding (null)
import qualified Data.IxSet as IxSet
import Data.Monoid
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Text (Text)
import Web.RBB.Crawler.MetaParser as M
import Web.RBB.Types.Entry
data MetaDataContractionState = S
{ _context :: Maybe FilePath
, _metaDataMap :: IxSet Entry
}
makeLenses ''MetaDataContractionState
-- | Add the given meta information to the giten 'IxSet'.
contract :: Maybe FilePath -- ^ Content relative path for an 'Entry'
-> [Meta] -- ^ Parsed meta information to add
-> IxSet Entry -- ^ Original entry 'IxSet'
-> IxSet Entry
contract initialContext meta m =
let initialState = S initialContext m
in execState (mapM_ contract' meta) initialState ^. metaDataMap
contract' :: Meta -> State MetaDataContractionState ()
contract' (Context c) = context .= Just c
contract' None = return ()
contract' meta = maybe (return ()) (updateMetaData meta) =<< use context
updateMetaDataMap :: FilePath
-> (Entry -> Entry)
-> State MetaDataContractionState ()
updateMetaDataMap c f = do
m <- use metaDataMap
let ixC = RelativePath c
case getOne $ m @= ixC of
Nothing -> return ()
Just e -> do
metaDataMap %= IxSet.deleteIx ixC
metaDataMap %= IxSet.insert (f e)
updateMetaData :: Meta -> FilePath -> State MetaDataContractionState ()
updateMetaData meta c = case meta of
M.Tags ts -> updateMetaDataMap c $ tags %~ updateTags ts
~(M.Title t) -> updateMetaDataMap c $ title .~ t
updateTags :: [(TagQuantifier, Text)] -> Set Text -> Set Text
updateTags ts tset
| null reps = foldr update tset ts
| otherwise = foldr update mempty ts
where
reps = filter ((== TagReplace) . fst) ts
update (TagRemove, t) = Set.delete t
update (_, t) = Set.insert t