summaryrefslogtreecommitdiff
path: root/Model.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Model.hs')
-rw-r--r--Model.hs90
1 files changed, 81 insertions, 9 deletions
diff --git a/Model.hs b/Model.hs
index 7b33f6e..a345f2f 100644
--- a/Model.hs
+++ b/Model.hs
@@ -10,7 +10,10 @@ import Control.Monad.Writer
10import Data.Text (Text) 10import Data.Text (Text)
11import qualified Data.Text as Text 11import qualified Data.Text as Text
12 12
13import qualified Data.HashMap.Lazy as HashMap
14
13import Data.Aeson 15import Data.Aeson
16import Data.Aeson.Types (Parser, Value(..))
14 17
15-- You can define all of your database entities in the entities file. 18-- You can define all of your database entities in the entities file.
16-- You can find more information on persistent and how to declare entities 19-- You can find more information on persistent and how to declare entities
@@ -19,6 +22,28 @@ import Data.Aeson
19share [mkPersist sqlSettings, mkMigrate "migrateAll"] 22share [mkPersist sqlSettings, mkMigrate "migrateAll"]
20 $(persistFileWith lowerCaseSettings "config/models") 23 $(persistFileWith lowerCaseSettings "config/models")
21 24
25class HasType a where
26 getType :: ( BaseBackend backend ~ SqlBackend
27 , MonadIO m
28 , PersistStoreRead backend
29 ) => a -> ReaderT backend m Kind
30
31instance HasType Item where
32 getType = belongsToJust itemFkType
33
34instance HasType Reference where
35 getType = belongsToJust referenceFkType
36
37instance HasType a => HasType (Entity a) where
38 getType Entity{..} = getType entityVal
39
40withType :: ( BaseBackend backend ~ SqlBackend
41 , MonadIO m
42 , PersistStoreRead backend
43 , HasType a
44 ) => a -> ReaderT backend m (WithType a)
45withType val = (val `WithType`) . kindType <$> getType val
46
22instance Ord Item where 47instance Ord Item where
23 x `compare` y = mconcat 48 x `compare` y = mconcat
24 [ (isNothing $ itemOpened x) `compare` (isNothing $ itemOpened y) 49 [ (isNothing $ itemOpened x) `compare` (isNothing $ itemOpened y)
@@ -71,6 +96,7 @@ normalizeKind :: Text -> Text
71normalizeKind = Text.strip . Text.toCaseFold 96normalizeKind = Text.strip . Text.toCaseFold
72 97
73data ItemDiff = DiffKind Text 98data ItemDiff = DiffKind Text
99 | DiffType Text
74 | DiffBought (Maybe Day) 100 | DiffBought (Maybe Day)
75 | DiffExpires (Maybe Day) 101 | DiffExpires (Maybe Day)
76 | DiffOpened (Maybe Day) 102 | DiffOpened (Maybe Day)
@@ -80,17 +106,63 @@ newtype ItemDiffs = ItemDiffs [ItemDiff]
80instance FromJSON ItemDiffs where 106instance FromJSON ItemDiffs where
81 parseJSON = withObject "ItemDiff" $ \obj -> fmap ItemDiffs . execWriterT $ do 107 parseJSON = withObject "ItemDiff" $ \obj -> fmap ItemDiffs . execWriterT $ do
82 tell =<< maybe [] (pure . DiffKind) <$> lift (obj .:? "kind") 108 tell =<< maybe [] (pure . DiffKind) <$> lift (obj .:? "kind")
109 tell =<< maybe [] (pure . DiffType) <$> lift (obj .:? "type")
83 tell =<< maybe [] (pure . DiffBought) <$> lift (obj .:! "bought") 110 tell =<< maybe [] (pure . DiffBought) <$> lift (obj .:! "bought")
84 tell =<< maybe [] (pure . DiffExpires) <$> lift (obj .:! "expires") 111 tell =<< maybe [] (pure . DiffExpires) <$> lift (obj .:! "expires")
85 tell =<< maybe [] (pure . DiffOpened) <$> lift (obj .:! "opened") 112 tell =<< maybe [] (pure . DiffOpened) <$> lift (obj .:! "opened")
86 113
87toUpdate :: ItemDiffs -> [Update Item] 114toUpdate :: ItemDiffs -> ([Update Item], [Update Kind])
88toUpdate (ItemDiffs ds) = do 115toUpdate (ItemDiffs ds) = mconcat $ do
89 x <- ds 116 x <- ds
90 case x of 117 return $ case x of
91 DiffKind t -> [ ItemKind =. t 118 DiffKind t -> (, []) [ ItemKind =. t
92 , ItemNormKind =. normalizeKind t 119 , ItemNormKind =. normalizeKind t
93 ] 120 ]
94 DiffBought d -> [ ItemBought =. d ] 121 DiffType t -> ([], ) [ KindType =. t ]
95 DiffExpires d -> [ ItemExpires =. d ] 122 DiffBought d -> (, []) [ ItemBought =. d ]
96 DiffOpened d -> [ ItemOpened =. d ] 123 DiffExpires d -> (, []) [ ItemExpires =. d ]
124 DiffOpened d -> (, []) [ ItemOpened =. d ]
125
126data WithType a = WithType { typedVal :: a, valType :: Text }
127 deriving (Eq, Ord)
128
129typeToJSON :: ToJSON a
130 => Text -- ^ Key for value, if needed
131 -> WithType a -> Value
132typeToJSON valKey (record `WithType` t) = Object $ HashMap.insert "type" (toJSON t) o
133 where
134 o
135 | Object o' <- toJSON record = o'
136 | otherwise = HashMap.singleton valKey $ toJSON record
137
138typeFromJSON :: FromJSON a
139 => Maybe Text -- ^ Key for value, if needed
140 -> Value -> Parser (WithType a)
141typeFromJSON valKey = withObject "value with type" $ \obj -> do
142 t <- obj .: "type"
143 value <- case valKey of
144 Just key -> parseJSON =<< obj .: key
145 Nothing -> parseJSON $ Object obj
146 return $ value `WithType` t
147
148instance ToJSON (WithType Item) where
149 toJSON = typeToJSON $ error "Item is not serializing correctly"
150
151instance ToJSON (WithType (Entity Item)) where
152 toJSON = typeToJSON $ error "Entity Item is not serializing correctly"
153
154instance ToJSON (WithType Reference) where
155 toJSON = typeToJSON "kind"
156
157instance ToJSON (WithType (Entity Reference)) where
158 toJSON ((Entity eId ref) `WithType` t) = object
159 [ "id" .= eId
160 , "type" .= t
161 , "kind" .= referenceKind ref
162 ]
163
164instance FromJSON (WithType Item) where
165 parseJSON = typeFromJSON Nothing
166
167instance FromJSON (WithType Reference) where
168 parseJSON = typeFromJSON $ Just "kind"