-- | -- Copyright : (c) 2008 Mathieu Boespflug -- License : LGPL -- Maintainer : mboes@tweag.net -- Stability : experimental -- Portability : portable -- -- Convenience functions to extract values in vCards and mapping over -- these values. module Text.VCard.Query where import Text.VCard.Types import qualified Codec.MIME.ContentType.Text.Directory as D import qualified Data.Map as Map import Data.Maybe (fromJust) import qualified Data.ByteString.Lazy.Char8.Caseless as I -- | Analog to |Data.List.lookup|. In general an attribute may map to a number -- of values. vCards should maintain the invariant that @forall attr, lookup -- attr vcard /= Just []@. lookup :: I.ByteString -> VCard -> Maybe [VCardValue] lookup typ vcard = fmap (Prelude.map D.prop_value) $ Map.lookup typ (vcard_properties vcard) -- | Unsafe variant of |lookup| that assumes given type name maps to exactly -- one value in the vCard. lookup' :: I.ByteString -> VCard -> VCardValue lookup' typ vcard = D.prop_value $ head $ fromJust $ Map.lookup typ (vcard_properties vcard) insert :: VProperty -> VCard -> VCard insert p vcard@(VCard {vcard_properties = attrs}) = vcard{ vcard_properties = Map.insertWith merge (D.type_name (D.prop_type p)) [p] attrs } where merge [p] ps = p:ps -- | Supports the most general filter predicates of the @filter@ family of functions. filterWithProperty :: (VProperty -> Bool) -> [VCard] -> [VCard] filterWithProperty f = Prelude.filter (not . Map.null . (Map.filter (not . null . Prelude.filter f) . vcard_properties)) -- | A specialization of |filterWithProperty|. filterWithType :: (D.Type -> VCardValue -> Bool) -> [VCard] -> [VCard] filterWithType f = filterWithProperty (\prop -> f (D.prop_type prop) (D.prop_value prop)) -- | Filter by property value only. filter :: (VCardValue -> Bool) -> [VCard] -> [VCard] filter f = filterWithProperty (\prop -> f (D.prop_value prop)) -- | Supports the most general map predicates of the @map@ family of functions. mapWithProperty :: (VProperty -> VCardValue) -> [VCard] -> [VCard] mapWithProperty f = Prelude.map updateVCard where updateProp prop = prop { D.prop_value = (f prop) } updateVCard vcard = vcard { vcard_properties = Map.map (Prelude.map updateProp) (vcard_properties vcard) } -- | A specialization of |mapWithProperty|. mapWithType :: (D.Type -> VCardValue -> VCardValue) -> [VCard] -> [VCard] mapWithType f = mapWithProperty (\prop -> f (D.prop_type prop) (D.prop_value prop)) -- | Map by property value only. map :: (VCardValue -> VCardValue) -> [VCard] -> [VCard] map f = mapWithProperty (\prop -> f (D.prop_value prop))