module Hope.Item.Types where import Hope.User.Types import Hope.Util import Hope.Util.List import Hope.Util.Path import Control.Monad (join) import Control.Monad.Error () import Data.Map (Map) import qualified Data.Map as Map import Data.Maybe (fromMaybe) import Data.Set (Set) import qualified Data.Set as Set import System.Time (CalendarTime) -- * Converting to and from the Item type class ITEM a where getItemType :: a -- ^ Dummy argument which will never be used. -> ItemType toItem :: a -> Item fromItem :: Item -> a -- * Items type ItemID = Int type ItemType = String type ItemKey = (ItemType, ItemID) data Item = Item { itemType :: ItemType, itemID :: ItemID, itemTitle :: String, itemOwner :: Maybe UserID, itemDate :: Maybe CalendarTime, itemDescription :: String, itemTags :: Tags, itemProperties :: Properties } deriving (Eq,Ord,Show) itemKey :: Item -> ItemKey itemKey it = (itemType it, itemID it) itemPath :: ITEM a => a -> Path itemPath = itemKeyPath . itemKey . toItem itemKeyPath :: ItemKey -> Path itemKeyPath (t,i) = [t,show i] showItemKey :: ItemKey -> String showItemKey = showPath . itemKeyPath itemError :: Item -> String -> a itemError it s = error $ showItemKey (itemType it, itemID it) ++ ": " ++ s itemRequired :: String -> (Item -> Maybe a) -> Item -> a itemRequired n s it = fromMaybe (itemError it (n ++ " is Nothing.")) (s it) -- * Properties type PropertyName = String type PropertyValue = String type Properties = Map PropertyName (Maybe PropertyValue) noProperties :: Properties noProperties = Map.empty mkProperties :: [(PropertyName, Maybe PropertyValue)] -> Properties mkProperties = Map.fromList itemGetProperty :: PropertyName -> Item -> Maybe PropertyValue itemGetProperty p it = join $ Map.lookup p (itemProperties it) itemGetPropertyOrFail :: PropertyName -> Item -> PropertyValue itemGetPropertyOrFail p it = fromMaybe (itemError it (p ++ " not set.")) $ itemGetProperty p it itemReadProperty :: Read a => String -> Item -> a itemReadProperty n it = either err id $ readM $ itemGetPropertyOrFail n it where err e = itemError it (n ++ ": " ++ e) -- * Tags type Tag = String type Tags = Set Tag noTags :: Tags noTags = Set.empty mkTags :: [Tag] -> Tags mkTags = Set.fromList . filter (not . null) . map trimSpace addTags :: Tags -> Tags -> Tags addTags = Set.union listTags :: Tags -> [Tag] listTags = Set.toList -- * Ordering data ItemOrder = ItemOrder { orderField :: OrderField, orderDir :: OrderDir } | ItemNoOrder deriving (Eq,Show) data OrderDir = OrderAsc | OrderDesc deriving (Eq,Show) data OrderField = OrderDate | OrderTitle | OrderProperty PropertyName deriving (Eq,Show) noOrder :: ItemOrder noOrder = ItemNoOrder dateAsc :: ItemOrder dateAsc = ItemOrder { orderField = OrderDate, orderDir = OrderAsc } dateDesc :: ItemOrder dateDesc = ItemOrder { orderField = OrderDate, orderDir = OrderDesc }