module Ganeti.Utils.MultiMap
( MultiMap()
, multiMap
, multiMapL
, multiMapValueL
, null
, findValue
, elem
, lookup
, member
, insert
, fromList
, delete
, deleteAll
, values
) where
import Prelude hiding (lookup, null, elem)
import Control.Monad
import qualified Data.Foldable as F
import qualified Data.Map as M
import Data.Maybe (fromMaybe, isJust)
import Data.Monoid
import qualified Data.Set as S
import qualified Text.JSON as J
import Ganeti.Lens
newtype MultiMap k v = MultiMap { getMultiMap :: M.Map k (S.Set v) }
deriving (Eq, Ord, Show)
instance (Ord v, Ord k) => Monoid (MultiMap k v) where
mempty = MultiMap M.empty
mappend (MultiMap x) (MultiMap y) = MultiMap $ M.unionWith S.union x y
instance F.Foldable (MultiMap k) where
foldMap f = F.foldMap (F.foldMap f) . getMultiMap
instance (J.JSON k, Ord k, J.JSON v, Ord v) => J.JSON (MultiMap k v) where
showJSON = J.showJSON . getMultiMap
readJSON = liftM MultiMap . J.readJSON
multiMap :: (Ord k, Ord v) => M.Map k (S.Set v) -> MultiMap k v
multiMap = MultiMap . M.filter (not . S.null)
multiMapL :: (Ord k, Ord v) => k -> Lens' (MultiMap k v) (S.Set v)
multiMapL k f = fmap MultiMap
. at k (fmap (mfilter (not . S.null) . Just)
. f . fromMaybe S.empty)
. getMultiMap
lookup :: (Ord k, Ord v) => k -> MultiMap k v -> S.Set v
lookup = view . multiMapL
member :: (Ord k, Ord v) => k -> MultiMap k v -> Bool
member = (S.null .) . lookup
findValue :: (Ord k, Ord v) => v -> MultiMap k v -> Maybe k
findValue v = fmap fst . F.find (S.member v . snd) . M.toList . getMultiMap
elem :: (Ord k, Ord v) => v -> MultiMap k v -> Bool
elem = (isJust .) . findValue
null :: MultiMap k v -> Bool
null = M.null . getMultiMap
insert :: (Ord k, Ord v) => k -> v -> MultiMap k v -> MultiMap k v
insert k v = set (multiMapValueL k v) True
fromList :: (Ord k, Ord v) => [(k, v)] -> MultiMap k v
fromList = foldr (uncurry insert) mempty
delete :: (Ord k, Ord v) => k -> v -> MultiMap k v -> MultiMap k v
delete k v = set (multiMapValueL k v) False
deleteAll :: (Ord k, Ord v) => k -> MultiMap k v -> MultiMap k v
deleteAll k = set (multiMapL k) S.empty
values :: (Ord k, Ord v) => MultiMap k v -> S.Set v
values = F.fold . getMultiMap
multiMapValueL :: (Ord k, Ord v) => k -> v -> Lens' (MultiMap k v) Bool
multiMapValueL k v = multiMapL k . atSet v