3 {-# LANGUAGE ConstraintKinds #-}
4 {-# LANGUAGE ScopedTypeVariables #-}
5 {-# LANGUAGE TemplateHaskell #-}
6 {-# LANGUAGE TypeOperators #-}
7 {-# LANGUAGE TypeFamilies #-}
8 {-# OPTIONS -fno-warn-orphans #-}
10 module Gargantext.API.Ngrams.Types where
12 import Codec.Serialise (Serialise())
13 import Control.Category ((>>>))
14 import Control.DeepSeq (NFData)
15 import Control.Lens (makeLenses, makePrisms, Iso', iso, from, (.~), (?=), (#), to, folded, {-withIndex, ifolded,-} view, use, (^.), (^?), (%~), (.~), (%=), at, _Just, Each(..), itraverse_, both, forOf_, (?~))
16 import Control.Monad.State
17 import Data.Aeson hiding ((.=))
18 import Data.Aeson.TH (deriveJSON)
19 import Data.Either (Either(..))
21 import Data.Hashable (Hashable)
22 import Data.Map.Strict (Map)
23 import Data.Maybe (fromMaybe)
25 import Data.Patch.Class (Replace, replace, Action(act), Group, Applicable(..), Composable(..), Transformable(..), PairPatch(..), Patched, ConflictResolution, ConflictResolutionReplace, MaybePatch(Mod), unMod, old, new)
27 import Data.String (IsString, fromString)
28 import Data.Swagger hiding (version, patch)
29 import Data.Text (Text, pack, strip)
31 import Database.PostgreSQL.Simple.FromField (FromField, fromField, fromJSONField)
32 import Database.PostgreSQL.Simple.ToField (ToField, toJSONField, toField)
33 import GHC.Generics (Generic)
34 import Gargantext.Core.Text (size)
35 import Gargantext.Core.Types (ListType(..), ListId, NodeId, TODO)
36 import Gargantext.Core.Utils.Prefix (unPrefix, unPrefixUntagged, unPrefixSwagger, wellNamedSchema)
37 import Gargantext.Database.Prelude (fromField', HasConnectionPool, HasConfig, CmdM')
38 import Gargantext.Prelude
39 import Gargantext.Prelude.Crypto.Hash (IsHashable(..))
40 import Protolude (maybeToEither)
41 import Servant hiding (Patch)
42 import Servant.Job.Utils (jsonOptions)
43 -- import System.FileLock (FileLock)
44 import Test.QuickCheck (elements, frequency)
45 import Test.QuickCheck.Arbitrary (Arbitrary, arbitrary)
46 import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap
47 import qualified Data.Map.Strict as Map
48 import qualified Data.Map.Strict.Patch as PM
49 import qualified Data.Set as Set
50 import qualified Gargantext.Database.Query.Table.Ngrams as TableNgrams
52 ------------------------------------------------------------------------
54 type QueryParamR = QueryParam' '[Required, Strict]
56 ------------------------------------------------------------------------
57 --data FacetFormat = Table | Chart
58 data TabType = Docs | Trash | MoreFav | MoreTrash
59 | Terms | Sources | Authors | Institutes
61 deriving (Bounded, Enum, Eq, Generic, Ord, Show)
64 instance Hashable TabType
66 instance FromHttpApiData TabType where
67 parseUrlPiece "Docs" = pure Docs
68 parseUrlPiece "Trash" = pure Trash
69 parseUrlPiece "MoreFav" = pure MoreFav
70 parseUrlPiece "MoreTrash" = pure MoreTrash
72 parseUrlPiece "Terms" = pure Terms
73 parseUrlPiece "Sources" = pure Sources
74 parseUrlPiece "Institutes" = pure Institutes
75 parseUrlPiece "Authors" = pure Authors
77 parseUrlPiece "Contacts" = pure Contacts
79 parseUrlPiece _ = Left "Unexpected value of TabType"
80 instance ToHttpApiData TabType where
81 toUrlPiece = pack . show
82 instance ToParamSchema TabType
83 instance ToJSON TabType
84 instance FromJSON TabType
85 instance ToSchema TabType
86 instance Arbitrary TabType where
87 arbitrary = elements [minBound .. maxBound]
88 instance FromJSONKey TabType where
89 fromJSONKey = genericFromJSONKey defaultJSONKeyOptions
90 instance ToJSONKey TabType where
91 toJSONKey = genericToJSONKey defaultJSONKeyOptions
93 newtype MSet a = MSet (Map a ())
94 deriving (Eq, Ord, Show, Generic, Arbitrary, Semigroup, Monoid)
96 instance ToJSON a => ToJSON (MSet a) where
97 toJSON (MSet m) = toJSON (Map.keys m)
98 toEncoding (MSet m) = toEncoding (Map.keys m)
100 mSetFromSet :: Set a -> MSet a
101 mSetFromSet = MSet . Map.fromSet (const ())
103 mSetFromList :: Ord a => [a] -> MSet a
104 mSetFromList = MSet . Map.fromList . map (\x -> (x, ()))
106 -- mSetToSet :: Ord a => MSet a -> Set a
107 -- mSetToSet (MSet a) = Set.fromList ( Map.keys a)
108 mSetToSet :: Ord a => MSet a -> Set a
109 mSetToSet = Set.fromList . mSetToList
111 mSetToList :: MSet a -> [a]
112 mSetToList (MSet a) = Map.keys a
114 instance Foldable MSet where
115 foldMap f (MSet m) = Map.foldMapWithKey (\k _ -> f k) m
117 instance (Ord a, FromJSON a) => FromJSON (MSet a) where
118 parseJSON = fmap mSetFromList . parseJSON
120 instance (ToJSONKey a, ToSchema a) => ToSchema (MSet a) where
122 declareNamedSchema _ = wellNamedSchema "" (Proxy :: Proxy TODO)
124 ------------------------------------------------------------------------
125 newtype NgramsTerm = NgramsTerm { unNgramsTerm :: Text }
126 deriving (Ord, Eq, Show, Generic, ToJSONKey, ToJSON, FromJSON, Semigroup, Arbitrary, Serialise, ToSchema, Hashable, NFData, FromField, ToField)
127 instance IsHashable NgramsTerm where
128 hash (NgramsTerm t) = hash t
129 instance Monoid NgramsTerm where
130 mempty = NgramsTerm ""
131 instance FromJSONKey NgramsTerm where
132 fromJSONKey = FromJSONKeyTextParser $ \t -> pure $ NgramsTerm $ strip t
133 instance IsString NgramsTerm where
134 fromString s = NgramsTerm $ pack s
137 data RootParent = RootParent
138 { _rp_root :: NgramsTerm
139 , _rp_parent :: NgramsTerm
141 deriving (Ord, Eq, Show, Generic)
143 deriveJSON (unPrefix "_rp_") ''RootParent
144 makeLenses ''RootParent
146 data NgramsRepoElement = NgramsRepoElement
148 , _nre_list :: !ListType
149 , _nre_root :: !(Maybe NgramsTerm)
150 , _nre_parent :: !(Maybe NgramsTerm)
151 , _nre_children :: !(MSet NgramsTerm)
153 deriving (Ord, Eq, Show, Generic)
154 deriveJSON (unPrefix "_nre_") ''NgramsRepoElement
156 -- if ngrams & not size => size
158 makeLenses ''NgramsRepoElement
159 instance ToSchema NgramsRepoElement where
160 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_nre_")
161 instance Serialise NgramsRepoElement
162 instance FromField NgramsRepoElement where
163 fromField = fromJSONField
164 instance ToField NgramsRepoElement where
165 toField = toJSONField
167 instance Serialise (MSet NgramsTerm)
170 NgramsElement { _ne_ngrams :: NgramsTerm
172 , _ne_list :: ListType
173 , _ne_occurrences :: Int
174 , _ne_root :: Maybe NgramsTerm
175 , _ne_parent :: Maybe NgramsTerm
176 , _ne_children :: MSet NgramsTerm
178 deriving (Ord, Eq, Show, Generic)
180 deriveJSON (unPrefix "_ne_") ''NgramsElement
181 makeLenses ''NgramsElement
183 mkNgramsElement :: NgramsTerm
188 mkNgramsElement ngrams list rp children =
189 NgramsElement ngrams (size (unNgramsTerm ngrams)) list 1 (_rp_root <$> rp) (_rp_parent <$> rp) children
191 newNgramsElement :: Maybe ListType -> NgramsTerm -> NgramsElement
192 newNgramsElement mayList ngrams =
193 mkNgramsElement ngrams (fromMaybe MapTerm mayList) Nothing mempty
195 instance ToSchema NgramsElement where
196 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_ne_")
197 instance Arbitrary NgramsElement where
198 arbitrary = elements [newNgramsElement Nothing "sport"]
201 ------------------------------------------------------------------------
202 newtype NgramsTable = NgramsTable [NgramsElement]
203 deriving (Ord, Eq, Generic, ToJSON, FromJSON, Show)
205 -- type NgramsList = NgramsTable
207 makePrisms ''NgramsTable
209 -- | Question: why these repetition of Type in this instance
210 -- may you document it please ?
211 instance Each NgramsTable NgramsTable NgramsElement NgramsElement where
212 each = _NgramsTable . each
215 -- | TODO Check N and Weight
217 toNgramsElement :: [NgramsTableData] -> [NgramsElement]
218 toNgramsElement ns = map toNgramsElement' ns
220 toNgramsElement' (NgramsTableData _ p t _ lt w) = NgramsElement t lt' (round w) p' c'
224 Just x -> lookup x mapParent
225 c' = maybe mempty identity $ lookup t mapChildren
226 lt' = maybe (panic "API.Ngrams: listypeId") identity lt
228 mapParent :: Map Int Text
229 mapParent = Map.fromListWith (<>) $ map (\(NgramsTableData i _ t _ _ _) -> (i,t)) ns
231 mapChildren :: Map Text (Set Text)
232 mapChildren = Map.mapKeys (\i -> (maybe (panic "API.Ngrams.mapChildren: ParentId with no Terms: Impossible") identity $ lookup i mapParent))
233 $ Map.fromListWith (<>)
234 $ map (first fromJust)
235 $ filter (isJust . fst)
236 $ map (\(NgramsTableData _ p t _ _ _) -> (p, Set.singleton t)) ns
239 mockTable :: NgramsTable
240 mockTable = NgramsTable
241 [ mkNgramsElement "animal" MapTerm Nothing (mSetFromList ["dog", "cat"])
242 , mkNgramsElement "cat" MapTerm (rp "animal") mempty
243 , mkNgramsElement "cats" StopTerm Nothing mempty
244 , mkNgramsElement "dog" MapTerm (rp "animal") (mSetFromList ["dogs"])
245 , mkNgramsElement "dogs" StopTerm (rp "dog") mempty
246 , mkNgramsElement "fox" MapTerm Nothing mempty
247 , mkNgramsElement "object" CandidateTerm Nothing mempty
248 , mkNgramsElement "nothing" StopTerm Nothing mempty
249 , mkNgramsElement "organic" MapTerm Nothing (mSetFromList ["flower"])
250 , mkNgramsElement "flower" MapTerm (rp "organic") mempty
251 , mkNgramsElement "moon" CandidateTerm Nothing mempty
252 , mkNgramsElement "sky" StopTerm Nothing mempty
255 rp n = Just $ RootParent n n
257 instance Arbitrary NgramsTable where
258 arbitrary = pure mockTable
260 instance ToSchema NgramsTable
262 ------------------------------------------------------------------------
263 type NgramsTableMap = Map NgramsTerm NgramsRepoElement
264 ------------------------------------------------------------------------
265 -- On the Client side:
266 --data Action = InGroup NgramsId NgramsId
267 -- | OutGroup NgramsId NgramsId
268 -- | SetListType NgramsId ListType
270 data PatchSet a = PatchSet
274 deriving (Eq, Ord, Show, Generic)
276 makeLenses ''PatchSet
277 makePrisms ''PatchSet
279 instance ToJSON a => ToJSON (PatchSet a) where
280 toJSON = genericToJSON $ unPrefix "_"
281 toEncoding = genericToEncoding $ unPrefix "_"
283 instance (Ord a, FromJSON a) => FromJSON (PatchSet a) where
284 parseJSON = genericParseJSON $ unPrefix "_"
287 instance (Ord a, Arbitrary a) => Arbitrary (PatchSet a) where
288 arbitrary = PatchSet <$> arbitrary <*> arbitrary
290 type instance Patched (PatchSet a) = Set a
292 type ConflictResolutionPatchSet a = SimpleConflictResolution' (Set a)
293 type instance ConflictResolution (PatchSet a) = ConflictResolutionPatchSet a
295 instance Ord a => Semigroup (PatchSet a) where
296 p <> q = PatchSet { _rem = (q ^. rem) `Set.difference` (p ^. add) <> p ^. rem
297 , _add = (q ^. add) `Set.difference` (p ^. rem) <> p ^. add
300 instance Ord a => Monoid (PatchSet a) where
301 mempty = PatchSet mempty mempty
303 instance Ord a => Group (PatchSet a) where
304 invert (PatchSet r a) = PatchSet a r
306 instance Ord a => Composable (PatchSet a) where
307 composable _ _ = undefined
309 instance Ord a => Action (PatchSet a) (Set a) where
310 act p source = (source `Set.difference` (p ^. rem)) <> p ^. add
312 instance Applicable (PatchSet a) (Set a) where
313 applicable _ _ = mempty
315 instance Ord a => Validity (PatchSet a) where
316 validate p = check (Set.disjoint (p ^. rem) (p ^. add)) "_rem and _add should be dijoint"
318 instance Ord a => Transformable (PatchSet a) where
319 transformable = undefined
321 conflicts _p _q = undefined
323 transformWith conflict p q = undefined conflict p q
325 instance ToSchema a => ToSchema (PatchSet a)
328 type AddRem = Replace (Maybe ())
330 instance Serialise AddRem
332 remPatch, addPatch :: AddRem
333 remPatch = replace (Just ()) Nothing
334 addPatch = replace Nothing (Just ())
336 isRem :: Replace (Maybe ()) -> Bool
337 isRem = (== remPatch)
339 type PatchMap = PM.PatchMap
341 newtype PatchMSet a = PatchMSet (PatchMap a AddRem)
342 deriving (Eq, Show, Generic, Validity, Semigroup, Monoid, Group,
343 Transformable, Composable)
345 unPatchMSet :: PatchMSet a -> PatchMap a AddRem
346 unPatchMSet (PatchMSet a) = a
348 type ConflictResolutionPatchMSet a = a -> ConflictResolutionReplace (Maybe ())
349 type instance ConflictResolution (PatchMSet a) = ConflictResolutionPatchMSet a
351 instance (Serialise a, Ord a) => Serialise (PatchMap a AddRem)
352 instance (Serialise a, Ord a) => Serialise (PatchMSet a)
354 -- TODO this breaks module abstraction
355 makePrisms ''PM.PatchMap
357 makePrisms ''PatchMSet
359 _PatchMSetIso :: Ord a => Iso' (PatchMSet a) (PatchSet a)
360 _PatchMSetIso = _PatchMSet . _PatchMap . iso f g . from _PatchSet
362 f :: Ord a => Map a (Replace (Maybe ())) -> (Set a, Set a)
363 f = Map.partition isRem >>> both %~ Map.keysSet
365 g :: Ord a => (Set a, Set a) -> Map a (Replace (Maybe ()))
366 g (rems, adds) = Map.fromSet (const remPatch) rems
367 <> Map.fromSet (const addPatch) adds
369 instance Ord a => Action (PatchMSet a) (MSet a) where
370 act (PatchMSet p) (MSet m) = MSet $ act p m
372 instance Ord a => Applicable (PatchMSet a) (MSet a) where
373 applicable (PatchMSet p) (MSet m) = applicable p m
375 instance (Ord a, ToJSON a) => ToJSON (PatchMSet a) where
376 toJSON = toJSON . view _PatchMSetIso
377 toEncoding = toEncoding . view _PatchMSetIso
379 instance (Ord a, FromJSON a) => FromJSON (PatchMSet a) where
380 parseJSON = fmap (_PatchMSetIso #) . parseJSON
382 instance (Ord a, Arbitrary a) => Arbitrary (PatchMSet a) where
383 arbitrary = (PatchMSet . PM.fromMap) <$> arbitrary
385 instance ToSchema a => ToSchema (PatchMSet a) where
387 declareNamedSchema _ = wellNamedSchema "" (Proxy :: Proxy TODO)
389 type instance Patched (PatchMSet a) = MSet a
391 instance (Eq a, Arbitrary a) => Arbitrary (Replace a) where
392 arbitrary = uncurry replace <$> arbitrary
393 -- If they happen to be equal then the patch is Keep.
395 instance ToSchema a => ToSchema (Replace a) where
396 declareNamedSchema (_ :: Proxy (Replace a)) = do
397 -- TODO Keep constructor is not supported here.
398 aSchema <- declareSchemaRef (Proxy :: Proxy a)
399 return $ NamedSchema (Just "Replace") $ mempty
400 & type_ ?~ SwaggerObject
402 InsOrdHashMap.fromList
406 & required .~ [ "old", "new" ]
409 = NgramsPatch { _patch_children :: !(PatchMSet NgramsTerm)
410 , _patch_list :: !(Replace ListType) -- TODO Map UserId ListType
412 | NgramsReplace { _patch_old :: !(Maybe NgramsRepoElement)
413 , _patch_new :: !(Maybe NgramsRepoElement)
415 deriving (Eq, Show, Generic)
417 -- The JSON encoding is untagged, this is OK since the field names are disjoints and thus the encoding is unambiguous.
418 -- TODO: the empty object should be accepted and treated as mempty.
419 deriveJSON (unPrefixUntagged "_") ''NgramsPatch
420 makeLenses ''NgramsPatch
422 -- TODO: This instance is simplified since we should either have the fields children and/or list
423 -- or the fields old and/or new.
424 instance ToSchema NgramsPatch where
425 declareNamedSchema _ = do
426 childrenSch <- declareSchemaRef (Proxy :: Proxy (PatchMSet NgramsTerm))
427 listSch <- declareSchemaRef (Proxy :: Proxy (Replace ListType))
428 nreSch <- declareSchemaRef (Proxy :: Proxy NgramsRepoElement)
429 return $ NamedSchema (Just "NgramsPatch") $ mempty
430 & type_ ?~ SwaggerObject
432 InsOrdHashMap.fromList
433 [ ("children", childrenSch)
438 instance Arbitrary NgramsPatch where
439 arbitrary = frequency [ (9, NgramsPatch <$> arbitrary <*> (replace <$> arbitrary <*> arbitrary))
440 , (1, NgramsReplace <$> arbitrary <*> arbitrary)
442 instance Serialise NgramsPatch
443 instance FromField NgramsPatch where
444 fromField = fromJSONField
445 instance ToField NgramsPatch where
446 toField = toJSONField
448 instance Serialise (Replace ListType)
450 instance Serialise ListType
452 type NgramsPatchIso =
453 MaybePatch NgramsRepoElement (PairPatch (PatchMSet NgramsTerm) (Replace ListType))
455 _NgramsPatch :: Iso' NgramsPatch NgramsPatchIso
456 _NgramsPatch = iso unwrap wrap
458 unwrap (NgramsPatch c l) = Mod $ PairPatch (c, l)
459 unwrap (NgramsReplace o n) = replace o n
462 Just (PairPatch (c, l)) -> NgramsPatch c l
463 Nothing -> NgramsReplace (x ^? old . _Just) (x ^? new . _Just)
465 instance Semigroup NgramsPatch where
466 p <> q = _NgramsPatch # (p ^. _NgramsPatch <> q ^. _NgramsPatch)
468 instance Monoid NgramsPatch where
469 mempty = _NgramsPatch # mempty
471 instance Validity NgramsPatch where
472 validate p = p ^. _NgramsPatch . to validate
474 instance Transformable NgramsPatch where
475 transformable p q = transformable (p ^. _NgramsPatch) (q ^. _NgramsPatch)
477 conflicts p q = conflicts (p ^. _NgramsPatch) (q ^. _NgramsPatch)
479 transformWith conflict p q = (_NgramsPatch # p', _NgramsPatch # q')
481 (p', q') = transformWith conflict (p ^. _NgramsPatch) (q ^. _NgramsPatch)
483 type ConflictResolutionNgramsPatch =
484 ( ConflictResolutionReplace (Maybe NgramsRepoElement)
485 , ( ConflictResolutionPatchMSet NgramsTerm
486 , ConflictResolutionReplace ListType
490 type instance ConflictResolution NgramsPatch =
491 ConflictResolutionNgramsPatch
493 type PatchedNgramsPatch = Maybe NgramsRepoElement
494 type instance Patched NgramsPatch = PatchedNgramsPatch
496 instance Applicable (PairPatch (PatchMSet NgramsTerm) (Replace ListType)) NgramsRepoElement where
497 applicable (PairPatch (c, l)) n = applicable c (n ^. nre_children) <> applicable l (n ^. nre_list)
499 instance Action (PairPatch (PatchMSet NgramsTerm) (Replace ListType)) NgramsRepoElement where
500 act (PairPatch (c, l)) = (nre_children %~ act c)
501 . (nre_list %~ act l)
503 instance Applicable NgramsPatch (Maybe NgramsRepoElement) where
504 applicable p = applicable (p ^. _NgramsPatch)
505 instance Action NgramsPatch (Maybe NgramsRepoElement) where
506 act p = act (p ^. _NgramsPatch)
508 newtype NgramsTablePatch = NgramsTablePatch (PatchMap NgramsTerm NgramsPatch)
509 deriving (Eq, Show, Generic, ToJSON, FromJSON, Semigroup, Monoid, Validity, Transformable)
511 instance Serialise NgramsTablePatch
512 instance Serialise (PatchMap NgramsTerm NgramsPatch)
514 instance FromField NgramsTablePatch
516 fromField = fromJSONField
517 --fromField = fromField'
518 instance ToField NgramsTablePatch
520 toField = toJSONField
522 instance FromField (PatchMap TableNgrams.NgramsType (PatchMap NodeId NgramsTablePatch))
524 fromField = fromField'
526 type instance ConflictResolution NgramsTablePatch =
527 NgramsTerm -> ConflictResolutionNgramsPatch
530 type PatchedNgramsTablePatch = Map NgramsTerm PatchedNgramsPatch
531 -- ~ Patched (PatchMap NgramsTerm NgramsPatch)
532 type instance Patched NgramsTablePatch = PatchedNgramsTablePatch
534 makePrisms ''NgramsTablePatch
535 instance ToSchema (PatchMap NgramsTerm NgramsPatch)
536 instance ToSchema NgramsTablePatch
538 instance Applicable NgramsTablePatch (Maybe NgramsTableMap) where
539 applicable p = applicable (p ^. _NgramsTablePatch)
542 ngramsElementToRepo :: NgramsElement -> NgramsRepoElement
544 (NgramsElement { _ne_size = s
558 ngramsElementFromRepo :: NgramsTerm -> NgramsRepoElement -> NgramsElement
559 ngramsElementFromRepo
568 NgramsElement { _ne_size = s
573 , _ne_ngrams = ngrams
574 , _ne_occurrences = 0 -- panic $ "API.Ngrams.Types._ne_occurrences"
576 -- Here we could use 0 if we want to avoid any `panic`.
577 -- It will not happen using getTableNgrams if
578 -- getOccByNgramsOnly provides a count of occurrences for
579 -- all the ngrams given.
583 reRootChildren :: NgramsTerm -> ReParent NgramsTerm
584 reRootChildren root ngram = do
585 nre <- use $ at ngram
586 forOf_ (_Just . nre_children . folded) nre $ \child -> do
587 at child . _Just . nre_root ?= root
588 reRootChildren root child
590 reParent :: Maybe RootParent -> ReParent NgramsTerm
591 reParent rp child = do
592 at child . _Just %= ( (nre_parent .~ (_rp_parent <$> rp))
593 . (nre_root .~ (_rp_root <$> rp))
595 reRootChildren (fromMaybe child (rp ^? _Just . rp_root)) child
597 reParentAddRem :: RootParent -> NgramsTerm -> ReParent AddRem
598 reParentAddRem rp child p =
599 reParent (if isRem p then Nothing else Just rp) child
601 reParentNgramsPatch :: NgramsTerm -> ReParent NgramsPatch
602 reParentNgramsPatch parent ngramsPatch = do
603 root_of_parent <- use (at parent . _Just . nre_root)
605 root = fromMaybe parent root_of_parent
606 rp = RootParent { _rp_root = root, _rp_parent = parent }
607 itraverse_ (reParentAddRem rp) (ngramsPatch ^. patch_children . _PatchMSet . _PatchMap)
608 -- TODO FoldableWithIndex/TraversableWithIndex for PatchMap
610 reParentNgramsTablePatch :: ReParent NgramsTablePatch
611 reParentNgramsTablePatch p = itraverse_ reParentNgramsPatch (p ^. _NgramsTablePatch. _PatchMap)
612 -- TODO FoldableWithIndex/TraversableWithIndex for PatchMap
614 ------------------------------------------------------------------------
616 instance Action NgramsTablePatch (Maybe NgramsTableMap) where
618 fmap (execState (reParentNgramsTablePatch p)) .
619 act (p ^. _NgramsTablePatch)
621 instance Arbitrary NgramsTablePatch where
622 arbitrary = NgramsTablePatch <$> PM.fromMap <$> arbitrary
624 -- Should it be less than an Lens' to preserve PatchMap's abstraction.
625 -- ntp_ngrams_patches :: Lens' NgramsTablePatch (Map NgramsTerm NgramsPatch)
626 -- ntp_ngrams_patches = _NgramsTablePatch . undefined
628 type ReParent a = forall m. MonadState NgramsTableMap m => a -> m ()
630 ------------------------------------------------------------------------
633 data Versioned a = Versioned
634 { _v_version :: Version
637 deriving (Generic, Show, Eq)
638 deriveJSON (unPrefix "_v_") ''Versioned
639 makeLenses ''Versioned
640 instance (Typeable a, ToSchema a) => ToSchema (Versioned a) where
641 declareNamedSchema = wellNamedSchema "_v_"
642 instance Arbitrary a => Arbitrary (Versioned a) where
643 arbitrary = Versioned 1 <$> arbitrary -- TODO 1 is constant so far
644 ------------------------------------------------------------------------
647 data VersionedWithCount a = VersionedWithCount
648 { _vc_version :: Version
652 deriving (Generic, Show, Eq)
653 deriveJSON (unPrefix "_vc_") ''VersionedWithCount
654 makeLenses ''VersionedWithCount
655 instance (Typeable a, ToSchema a) => ToSchema (VersionedWithCount a) where
656 declareNamedSchema = wellNamedSchema "_vc_"
657 instance Arbitrary a => Arbitrary (VersionedWithCount a) where
658 arbitrary = VersionedWithCount 1 1 <$> arbitrary -- TODO 1 is constant so far
660 toVersionedWithCount :: Count -> Versioned a -> VersionedWithCount a
661 toVersionedWithCount count (Versioned version data_) = VersionedWithCount version count data_
662 ------------------------------------------------------------------------
666 { _r_version :: !Version
669 -- first patch in the list is the most recent
671 deriving (Generic, Show)
673 ----------------------------------------------------------------------
675 instance (FromJSON s, FromJSON p) => FromJSON (Repo s p) where
676 parseJSON = genericParseJSON $ unPrefix "_r_"
678 instance (ToJSON s, ToJSON p) => ToJSON (Repo s p) where
679 toJSON = genericToJSON $ unPrefix "_r_"
680 toEncoding = genericToEncoding $ unPrefix "_r_"
682 instance (Serialise s, Serialise p) => Serialise (Repo s p)
686 initRepo :: Monoid s => Repo s p
687 initRepo = Repo 1 mempty []
693 type RepoCmdM env err m =
695 , HasConnectionPool env
700 ------------------------------------------------------------------------
704 instance Arbitrary NgramsRepoElement where
705 arbitrary = elements $ map ngramsElementToRepo ns
707 NgramsTable ns = mockTable
709 instance FromHttpApiData (Map TableNgrams.NgramsType (Versioned NgramsTableMap))
711 parseUrlPiece x = maybeToEither x (decode $ cs x)
713 instance ToHttpApiData (Map TableNgrams.NgramsType (Versioned NgramsTableMap)) where
714 toUrlPiece m = cs (encode m)
716 ngramsTypeFromTabType :: TabType -> TableNgrams.NgramsType
717 ngramsTypeFromTabType tabType =
718 let here = "Garg.API.Ngrams: " :: Text in
720 Sources -> TableNgrams.Sources
721 Authors -> TableNgrams.Authors
722 Institutes -> TableNgrams.Institutes
723 Terms -> TableNgrams.NgramsTerms
724 _ -> panic $ here <> "No Ngrams for this tab"
725 -- TODO: This `panic` would disapear with custom NgramsType.
730 data UpdateTableNgramsCharts = UpdateTableNgramsCharts
731 { _utn_tab_type :: !TabType
732 , _utn_list_id :: !ListId
733 } deriving (Eq, Show, Generic)
735 makeLenses ''UpdateTableNgramsCharts
736 instance FromJSON UpdateTableNgramsCharts where
737 parseJSON = genericParseJSON $ jsonOptions "_utn_"
739 instance ToJSON UpdateTableNgramsCharts where
740 toJSON = genericToJSON $ jsonOptions "_utn_"
742 instance ToSchema UpdateTableNgramsCharts where
743 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_utn_")
745 ------------------------------------------------------------------------
746 type NgramsList = (Map TableNgrams.NgramsType (Versioned NgramsTableMap))