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.Concurrent
15 import Control.Lens (makeLenses, makePrisms, Getter, Iso', iso, from, (.~), (?=), (#), to, folded, {-withIndex, ifolded,-} view, use, (^.), (^?), (%~), (.~), (%=), at, _Just, Each(..), itraverse_, both, forOf_, (?~))
16 import Control.Monad.Reader
17 import Control.Monad.State
18 import Data.Aeson hiding ((.=))
19 import Data.Aeson.TH (deriveJSON)
20 import Data.Either (Either(..))
22 import Data.Hashable (Hashable)
23 import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap
24 import qualified Data.List as List
25 import Data.Map.Strict (Map)
26 import qualified Data.Map.Strict as Map
27 import qualified Data.Map.Strict.Patch as PM
28 import Data.Maybe (fromMaybe)
30 import Data.Patch.Class (Replace, replace, Action(act), Group, Applicable(..), Composable(..), Transformable(..),
31 PairPatch(..), Patched, ConflictResolution, ConflictResolutionReplace,
32 MaybePatch(Mod), unMod, old, new)
34 import qualified Data.Set as Set
35 import Data.String (IsString, fromString)
36 import Data.Swagger hiding (version, patch)
37 import Data.Text (Text, pack, strip)
39 import Database.PostgreSQL.Simple.FromField (FromField, fromField, ResultError(ConversionFailed), returnError)
40 import GHC.Generics (Generic)
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)
47 import Protolude (maybeToEither)
48 import Gargantext.Prelude
50 import Gargantext.Core.Text (size)
51 import Gargantext.Core.Types (ListType(..), ListId, NodeId)
52 import Gargantext.Core.Types (TODO)
53 import Gargantext.Core.Utils.Prefix (unPrefix, unPrefixUntagged, unPrefixSwagger, wellNamedSchema)
54 import Gargantext.Database.Prelude (fromField', CmdM', HasConnectionPool, HasConfig)
55 import qualified Gargantext.Database.Query.Table.Ngrams as TableNgrams
57 ------------------------------------------------------------------------
58 --data FacetFormat = Table | Chart
59 data TabType = Docs | Trash | MoreFav | MoreTrash
60 | Terms | Sources | Authors | Institutes
62 deriving (Bounded, Enum, Eq, Generic, Ord, Show)
65 instance Hashable TabType
67 instance FromHttpApiData TabType
69 parseUrlPiece "Docs" = pure Docs
70 parseUrlPiece "Trash" = pure Trash
71 parseUrlPiece "MoreFav" = pure MoreFav
72 parseUrlPiece "MoreTrash" = pure MoreTrash
74 parseUrlPiece "Terms" = pure Terms
75 parseUrlPiece "Sources" = pure Sources
76 parseUrlPiece "Institutes" = pure Institutes
77 parseUrlPiece "Authors" = pure Authors
79 parseUrlPiece "Contacts" = pure Contacts
81 parseUrlPiece _ = Left "Unexpected value of TabType"
82 instance ToParamSchema TabType
83 instance ToJSON TabType
84 instance FromJSON TabType
85 instance ToSchema TabType
86 instance Arbitrary TabType
88 arbitrary = elements [minBound .. maxBound]
89 instance FromJSONKey TabType where
90 fromJSONKey = genericFromJSONKey defaultJSONKeyOptions
91 instance ToJSONKey TabType where
92 toJSONKey = genericToJSONKey defaultJSONKeyOptions
94 newtype MSet a = MSet (Map a ())
95 deriving (Eq, Ord, Show, Generic, Arbitrary, Semigroup, Monoid)
97 instance ToJSON a => ToJSON (MSet a) where
98 toJSON (MSet m) = toJSON (Map.keys m)
99 toEncoding (MSet m) = toEncoding (Map.keys m)
101 mSetFromSet :: Set a -> MSet a
102 mSetFromSet = MSet . Map.fromSet (const ())
104 mSetFromList :: Ord a => [a] -> MSet a
105 mSetFromList = MSet . Map.fromList . map (\x -> (x, ()))
107 -- mSetToSet :: Ord a => MSet a -> Set a
108 -- mSetToSet (MSet a) = Set.fromList ( Map.keys a)
109 mSetToSet :: Ord a => MSet a -> Set a
110 mSetToSet = Set.fromList . mSetToList
112 mSetToList :: MSet a -> [a]
113 mSetToList (MSet a) = Map.keys a
115 instance Foldable MSet where
116 foldMap f (MSet m) = Map.foldMapWithKey (\k _ -> f k) m
118 instance (Ord a, FromJSON a) => FromJSON (MSet a) where
119 parseJSON = fmap mSetFromList . parseJSON
121 instance (ToJSONKey a, ToSchema a) => ToSchema (MSet a) where
123 declareNamedSchema _ = wellNamedSchema "" (Proxy :: Proxy TODO)
125 ------------------------------------------------------------------------
126 newtype NgramsTerm = NgramsTerm { unNgramsTerm :: Text }
127 deriving (Ord, Eq, Show, Generic, ToJSONKey, ToJSON, FromJSON, Semigroup, Arbitrary, Serialise, ToSchema, Hashable)
129 instance FromJSONKey NgramsTerm where
130 fromJSONKey = FromJSONKeyTextParser $ \t -> pure $ NgramsTerm $ strip t
132 instance IsString NgramsTerm where
133 fromString s = NgramsTerm $ pack s
135 instance FromField NgramsTerm
137 fromField field mb = do
138 v <- fromField field mb
140 Success a -> pure $ NgramsTerm $ strip a
141 Error _err -> returnError ConversionFailed field
142 $ List.intercalate " " [ "cannot parse hyperdata for JSON: "
146 data RootParent = RootParent
147 { _rp_root :: NgramsTerm
148 , _rp_parent :: NgramsTerm
150 deriving (Ord, Eq, Show, Generic)
152 deriveJSON (unPrefix "_rp_") ''RootParent
153 makeLenses ''RootParent
155 data NgramsRepoElement = NgramsRepoElement
157 , _nre_list :: !ListType
158 , _nre_root :: !(Maybe NgramsTerm)
159 , _nre_parent :: !(Maybe NgramsTerm)
160 , _nre_children :: !(MSet NgramsTerm)
162 deriving (Ord, Eq, Show, Generic)
164 deriveJSON (unPrefix "_nre_") ''NgramsRepoElement
166 -- if ngrams & not size => size
169 makeLenses ''NgramsRepoElement
171 instance ToSchema NgramsRepoElement where
172 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_nre_")
174 instance Serialise (MSet NgramsTerm)
175 instance Serialise NgramsRepoElement
178 NgramsElement { _ne_ngrams :: NgramsTerm
180 , _ne_list :: ListType
181 , _ne_occurrences :: Int
182 , _ne_root :: Maybe NgramsTerm
183 , _ne_parent :: Maybe NgramsTerm
184 , _ne_children :: MSet NgramsTerm
186 deriving (Ord, Eq, Show, Generic)
188 deriveJSON (unPrefix "_ne_") ''NgramsElement
189 makeLenses ''NgramsElement
191 mkNgramsElement :: NgramsTerm
196 mkNgramsElement ngrams list rp children =
197 NgramsElement ngrams (size (unNgramsTerm ngrams)) list 1 (_rp_root <$> rp) (_rp_parent <$> rp) children
199 newNgramsElement :: Maybe ListType -> NgramsTerm -> NgramsElement
200 newNgramsElement mayList ngrams =
201 mkNgramsElement ngrams (fromMaybe MapTerm mayList) Nothing mempty
203 instance ToSchema NgramsElement where
204 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_ne_")
205 instance Arbitrary NgramsElement where
206 arbitrary = elements [newNgramsElement Nothing "sport"]
209 ------------------------------------------------------------------------
210 newtype NgramsTable = NgramsTable [NgramsElement]
211 deriving (Ord, Eq, Generic, ToJSON, FromJSON, Show)
213 type NgramsList = NgramsTable
215 makePrisms ''NgramsTable
217 -- | Question: why these repetition of Type in this instance
218 -- may you document it please ?
219 instance Each NgramsTable NgramsTable NgramsElement NgramsElement where
220 each = _NgramsTable . each
223 -- | TODO Check N and Weight
225 toNgramsElement :: [NgramsTableData] -> [NgramsElement]
226 toNgramsElement ns = map toNgramsElement' ns
228 toNgramsElement' (NgramsTableData _ p t _ lt w) = NgramsElement t lt' (round w) p' c'
232 Just x -> lookup x mapParent
233 c' = maybe mempty identity $ lookup t mapChildren
234 lt' = maybe (panic "API.Ngrams: listypeId") identity lt
236 mapParent :: Map Int Text
237 mapParent = Map.fromListWith (<>) $ map (\(NgramsTableData i _ t _ _ _) -> (i,t)) ns
239 mapChildren :: Map Text (Set Text)
240 mapChildren = Map.mapKeys (\i -> (maybe (panic "API.Ngrams.mapChildren: ParentId with no Terms: Impossible") identity $ lookup i mapParent))
241 $ Map.fromListWith (<>)
242 $ map (first fromJust)
243 $ filter (isJust . fst)
244 $ map (\(NgramsTableData _ p t _ _ _) -> (p, Set.singleton t)) ns
247 mockTable :: NgramsTable
248 mockTable = NgramsTable
249 [ mkNgramsElement "animal" MapTerm Nothing (mSetFromList ["dog", "cat"])
250 , mkNgramsElement "cat" MapTerm (rp "animal") mempty
251 , mkNgramsElement "cats" StopTerm Nothing mempty
252 , mkNgramsElement "dog" MapTerm (rp "animal") (mSetFromList ["dogs"])
253 , mkNgramsElement "dogs" StopTerm (rp "dog") mempty
254 , mkNgramsElement "fox" MapTerm Nothing mempty
255 , mkNgramsElement "object" CandidateTerm Nothing mempty
256 , mkNgramsElement "nothing" StopTerm Nothing mempty
257 , mkNgramsElement "organic" MapTerm Nothing (mSetFromList ["flower"])
258 , mkNgramsElement "flower" MapTerm (rp "organic") mempty
259 , mkNgramsElement "moon" CandidateTerm Nothing mempty
260 , mkNgramsElement "sky" StopTerm Nothing mempty
263 rp n = Just $ RootParent n n
265 instance Arbitrary NgramsTable where
266 arbitrary = pure mockTable
268 instance ToSchema NgramsTable
270 ------------------------------------------------------------------------
271 type NgramsTableMap = Map NgramsTerm NgramsRepoElement
272 ------------------------------------------------------------------------
273 -- On the Client side:
274 --data Action = InGroup NgramsId NgramsId
275 -- | OutGroup NgramsId NgramsId
276 -- | SetListType NgramsId ListType
278 data PatchSet a = PatchSet
282 deriving (Eq, Ord, Show, Generic)
284 makeLenses ''PatchSet
285 makePrisms ''PatchSet
287 instance ToJSON a => ToJSON (PatchSet a) where
288 toJSON = genericToJSON $ unPrefix "_"
289 toEncoding = genericToEncoding $ unPrefix "_"
291 instance (Ord a, FromJSON a) => FromJSON (PatchSet a) where
292 parseJSON = genericParseJSON $ unPrefix "_"
295 instance (Ord a, Arbitrary a) => Arbitrary (PatchSet a) where
296 arbitrary = PatchSet <$> arbitrary <*> arbitrary
298 type instance Patched (PatchSet a) = Set a
300 type ConflictResolutionPatchSet a = SimpleConflictResolution' (Set a)
301 type instance ConflictResolution (PatchSet a) = ConflictResolutionPatchSet a
303 instance Ord a => Semigroup (PatchSet a) where
304 p <> q = PatchSet { _rem = (q ^. rem) `Set.difference` (p ^. add) <> p ^. rem
305 , _add = (q ^. add) `Set.difference` (p ^. rem) <> p ^. add
308 instance Ord a => Monoid (PatchSet a) where
309 mempty = PatchSet mempty mempty
311 instance Ord a => Group (PatchSet a) where
312 invert (PatchSet r a) = PatchSet a r
314 instance Ord a => Composable (PatchSet a) where
315 composable _ _ = undefined
317 instance Ord a => Action (PatchSet a) (Set a) where
318 act p source = (source `Set.difference` (p ^. rem)) <> p ^. add
320 instance Applicable (PatchSet a) (Set a) where
321 applicable _ _ = mempty
323 instance Ord a => Validity (PatchSet a) where
324 validate p = check (Set.disjoint (p ^. rem) (p ^. add)) "_rem and _add should be dijoint"
326 instance Ord a => Transformable (PatchSet a) where
327 transformable = undefined
329 conflicts _p _q = undefined
331 transformWith conflict p q = undefined conflict p q
333 instance ToSchema a => ToSchema (PatchSet a)
336 type AddRem = Replace (Maybe ())
338 instance Serialise AddRem
340 remPatch, addPatch :: AddRem
341 remPatch = replace (Just ()) Nothing
342 addPatch = replace Nothing (Just ())
344 isRem :: Replace (Maybe ()) -> Bool
345 isRem = (== remPatch)
347 type PatchMap = PM.PatchMap
349 newtype PatchMSet a = PatchMSet (PatchMap a AddRem)
350 deriving (Eq, Show, Generic, Validity, Semigroup, Monoid, Group,
351 Transformable, Composable)
353 unPatchMSet :: PatchMSet a -> PatchMap a AddRem
354 unPatchMSet (PatchMSet a) = a
356 type ConflictResolutionPatchMSet a = a -> ConflictResolutionReplace (Maybe ())
357 type instance ConflictResolution (PatchMSet a) = ConflictResolutionPatchMSet a
359 instance (Serialise a, Ord a) => Serialise (PatchMap a AddRem)
360 instance (Serialise a, Ord a) => Serialise (PatchMSet a)
362 -- TODO this breaks module abstraction
363 makePrisms ''PM.PatchMap
365 makePrisms ''PatchMSet
367 _PatchMSetIso :: Ord a => Iso' (PatchMSet a) (PatchSet a)
368 _PatchMSetIso = _PatchMSet . _PatchMap . iso f g . from _PatchSet
370 f :: Ord a => Map a (Replace (Maybe ())) -> (Set a, Set a)
371 f = Map.partition isRem >>> both %~ Map.keysSet
373 g :: Ord a => (Set a, Set a) -> Map a (Replace (Maybe ()))
374 g (rems, adds) = Map.fromSet (const remPatch) rems
375 <> Map.fromSet (const addPatch) adds
377 instance Ord a => Action (PatchMSet a) (MSet a) where
378 act (PatchMSet p) (MSet m) = MSet $ act p m
380 instance Ord a => Applicable (PatchMSet a) (MSet a) where
381 applicable (PatchMSet p) (MSet m) = applicable p m
383 instance (Ord a, ToJSON a) => ToJSON (PatchMSet a) where
384 toJSON = toJSON . view _PatchMSetIso
385 toEncoding = toEncoding . view _PatchMSetIso
387 instance (Ord a, FromJSON a) => FromJSON (PatchMSet a) where
388 parseJSON = fmap (_PatchMSetIso #) . parseJSON
390 instance (Ord a, Arbitrary a) => Arbitrary (PatchMSet a) where
391 arbitrary = (PatchMSet . PM.fromMap) <$> arbitrary
393 instance ToSchema a => ToSchema (PatchMSet a) where
395 declareNamedSchema _ = wellNamedSchema "" (Proxy :: Proxy TODO)
397 type instance Patched (PatchMSet a) = MSet a
399 instance (Eq a, Arbitrary a) => Arbitrary (Replace a) where
400 arbitrary = uncurry replace <$> arbitrary
401 -- If they happen to be equal then the patch is Keep.
403 instance ToSchema a => ToSchema (Replace a) where
404 declareNamedSchema (_ :: Proxy (Replace a)) = do
405 -- TODO Keep constructor is not supported here.
406 aSchema <- declareSchemaRef (Proxy :: Proxy a)
407 return $ NamedSchema (Just "Replace") $ mempty
408 & type_ ?~ SwaggerObject
410 InsOrdHashMap.fromList
414 & required .~ [ "old", "new" ]
417 = NgramsPatch { _patch_children :: !(PatchMSet NgramsTerm)
418 , _patch_list :: !(Replace ListType) -- TODO Map UserId ListType
420 | NgramsReplace { _patch_old :: !(Maybe NgramsRepoElement)
421 , _patch_new :: !(Maybe NgramsRepoElement)
423 deriving (Eq, Show, Generic)
425 -- The JSON encoding is untagged, this is OK since the field names are disjoints and thus the encoding is unambiguous.
426 -- TODO: the empty object should be accepted and treated as mempty.
427 deriveJSON (unPrefixUntagged "_") ''NgramsPatch
428 makeLenses ''NgramsPatch
430 -- TODO: This instance is simplified since we should either have the fields children and/or list
431 -- or the fields old and/or new.
432 instance ToSchema NgramsPatch where
433 declareNamedSchema _ = do
434 childrenSch <- declareSchemaRef (Proxy :: Proxy (PatchMSet NgramsTerm))
435 listSch <- declareSchemaRef (Proxy :: Proxy (Replace ListType))
436 nreSch <- declareSchemaRef (Proxy :: Proxy NgramsRepoElement)
437 return $ NamedSchema (Just "NgramsPatch") $ mempty
438 & type_ ?~ SwaggerObject
440 InsOrdHashMap.fromList
441 [ ("children", childrenSch)
447 instance Arbitrary NgramsPatch where
448 arbitrary = frequency [ (9, NgramsPatch <$> arbitrary <*> (replace <$> arbitrary <*> arbitrary))
449 , (1, NgramsReplace <$> arbitrary <*> arbitrary)
452 instance Serialise NgramsPatch
453 instance Serialise (Replace ListType)
455 instance Serialise ListType
457 type NgramsPatchIso =
458 MaybePatch NgramsRepoElement (PairPatch (PatchMSet NgramsTerm) (Replace ListType))
460 _NgramsPatch :: Iso' NgramsPatch NgramsPatchIso
461 _NgramsPatch = iso unwrap wrap
463 unwrap (NgramsPatch c l) = Mod $ PairPatch (c, l)
464 unwrap (NgramsReplace o n) = replace o n
467 Just (PairPatch (c, l)) -> NgramsPatch c l
468 Nothing -> NgramsReplace (x ^? old . _Just) (x ^? new . _Just)
470 instance Semigroup NgramsPatch where
471 p <> q = _NgramsPatch # (p ^. _NgramsPatch <> q ^. _NgramsPatch)
473 instance Monoid NgramsPatch where
474 mempty = _NgramsPatch # mempty
476 instance Validity NgramsPatch where
477 validate p = p ^. _NgramsPatch . to validate
479 instance Transformable NgramsPatch where
480 transformable p q = transformable (p ^. _NgramsPatch) (q ^. _NgramsPatch)
482 conflicts p q = conflicts (p ^. _NgramsPatch) (q ^. _NgramsPatch)
484 transformWith conflict p q = (_NgramsPatch # p', _NgramsPatch # q')
486 (p', q') = transformWith conflict (p ^. _NgramsPatch) (q ^. _NgramsPatch)
488 type ConflictResolutionNgramsPatch =
489 ( ConflictResolutionReplace (Maybe NgramsRepoElement)
490 , ( ConflictResolutionPatchMSet NgramsTerm
491 , ConflictResolutionReplace ListType
495 type instance ConflictResolution NgramsPatch =
496 ConflictResolutionNgramsPatch
498 type PatchedNgramsPatch = Maybe NgramsRepoElement
499 type instance Patched NgramsPatch = PatchedNgramsPatch
501 instance Applicable (PairPatch (PatchMSet NgramsTerm) (Replace ListType)) NgramsRepoElement where
502 applicable (PairPatch (c, l)) n = applicable c (n ^. nre_children) <> applicable l (n ^. nre_list)
504 instance Action (PairPatch (PatchMSet NgramsTerm) (Replace ListType)) NgramsRepoElement where
505 act (PairPatch (c, l)) = (nre_children %~ act c)
506 . (nre_list %~ act l)
508 instance Applicable NgramsPatch (Maybe NgramsRepoElement) where
509 applicable p = applicable (p ^. _NgramsPatch)
511 instance Action NgramsPatch (Maybe NgramsRepoElement) where
512 act p = act (p ^. _NgramsPatch)
514 newtype NgramsTablePatch = NgramsTablePatch (PatchMap NgramsTerm NgramsPatch)
515 deriving (Eq, Show, Generic, ToJSON, FromJSON, Semigroup, Monoid, Validity, Transformable)
517 instance Serialise NgramsTablePatch
518 instance Serialise (PatchMap NgramsTerm NgramsPatch)
520 instance FromField NgramsTablePatch
522 fromField = fromField'
524 instance FromField (PatchMap TableNgrams.NgramsType (PatchMap NodeId NgramsTablePatch))
526 fromField = fromField'
528 type instance ConflictResolution NgramsTablePatch =
529 NgramsTerm -> ConflictResolutionNgramsPatch
531 type PatchedNgramsTablePatch = Map NgramsTerm PatchedNgramsPatch
532 -- ~ Patched (PatchMap NgramsTerm NgramsPatch)
533 type instance Patched NgramsTablePatch = PatchedNgramsTablePatch
535 makePrisms ''NgramsTablePatch
536 instance ToSchema (PatchMap NgramsTerm NgramsPatch)
537 instance ToSchema NgramsTablePatch
539 instance Applicable NgramsTablePatch (Maybe NgramsTableMap) where
540 applicable p = applicable (p ^. _NgramsTablePatch)
543 ngramsElementToRepo :: NgramsElement -> NgramsRepoElement
545 (NgramsElement { _ne_size = s
559 ngramsElementFromRepo :: NgramsTerm -> NgramsRepoElement -> NgramsElement
560 ngramsElementFromRepo
569 NgramsElement { _ne_size = s
574 , _ne_ngrams = ngrams
575 , _ne_occurrences = panic $ "API.Ngrams._ne_occurrences"
577 -- Here we could use 0 if we want to avoid any `panic`.
578 -- It will not happen using getTableNgrams if
579 -- getOccByNgramsOnly provides a count of occurrences for
580 -- all the ngrams given.
584 reRootChildren :: NgramsTerm -> ReParent NgramsTerm
585 reRootChildren root ngram = do
586 nre <- use $ at ngram
587 forOf_ (_Just . nre_children . folded) nre $ \child -> do
588 at child . _Just . nre_root ?= root
589 reRootChildren root child
591 reParent :: Maybe RootParent -> ReParent NgramsTerm
592 reParent rp child = do
593 at child . _Just %= ( (nre_parent .~ (_rp_parent <$> rp))
594 . (nre_root .~ (_rp_root <$> rp))
596 reRootChildren (fromMaybe child (rp ^? _Just . rp_root)) child
598 reParentAddRem :: RootParent -> NgramsTerm -> ReParent AddRem
599 reParentAddRem rp child p =
600 reParent (if isRem p then Nothing else Just rp) child
602 reParentNgramsPatch :: NgramsTerm -> ReParent NgramsPatch
603 reParentNgramsPatch parent ngramsPatch = do
604 root_of_parent <- use (at parent . _Just . nre_root)
606 root = fromMaybe parent root_of_parent
607 rp = RootParent { _rp_root = root, _rp_parent = parent }
608 itraverse_ (reParentAddRem rp) (ngramsPatch ^. patch_children . _PatchMSet . _PatchMap)
609 -- TODO FoldableWithIndex/TraversableWithIndex for PatchMap
611 reParentNgramsTablePatch :: ReParent NgramsTablePatch
612 reParentNgramsTablePatch p = itraverse_ reParentNgramsPatch (p ^. _NgramsTablePatch. _PatchMap)
613 -- TODO FoldableWithIndex/TraversableWithIndex for PatchMap
615 ------------------------------------------------------------------------
617 instance Action NgramsTablePatch (Maybe NgramsTableMap) where
619 fmap (execState (reParentNgramsTablePatch p)) .
620 act (p ^. _NgramsTablePatch)
622 instance Arbitrary NgramsTablePatch where
623 arbitrary = NgramsTablePatch <$> PM.fromMap <$> arbitrary
625 -- Should it be less than an Lens' to preserve PatchMap's abstraction.
626 -- ntp_ngrams_patches :: Lens' NgramsTablePatch (Map NgramsTerm NgramsPatch)
627 -- ntp_ngrams_patches = _NgramsTablePatch . undefined
629 type ReParent a = forall m. MonadState NgramsTableMap m => a -> m ()
631 ------------------------------------------------------------------------
634 data Versioned a = Versioned
635 { _v_version :: Version
638 deriving (Generic, Show, Eq)
639 deriveJSON (unPrefix "_v_") ''Versioned
640 makeLenses ''Versioned
641 instance (Typeable a, ToSchema a) => ToSchema (Versioned a) where
642 declareNamedSchema = wellNamedSchema "_v_"
643 instance Arbitrary a => Arbitrary (Versioned a) where
644 arbitrary = Versioned 1 <$> arbitrary -- TODO 1 is constant so far
646 ------------------------------------------------------------------------
648 { _r_version :: !Version
651 -- first patch in the list is the most recent
653 deriving (Generic, Show)
655 instance (FromJSON s, FromJSON p) => FromJSON (Repo s p) where
656 parseJSON = genericParseJSON $ unPrefix "_r_"
658 instance (ToJSON s, ToJSON p) => ToJSON (Repo s p) where
659 toJSON = genericToJSON $ unPrefix "_r_"
660 toEncoding = genericToEncoding $ unPrefix "_r_"
662 instance (Serialise s, Serialise p) => Serialise (Repo s p)
666 initRepo :: Monoid s => Repo s p
667 initRepo = Repo 1 mempty []
669 type NgramsRepo = Repo NgramsState NgramsStatePatch
670 type NgramsState = Map TableNgrams.NgramsType (Map NodeId NgramsTableMap)
671 type NgramsStatePatch = PatchMap TableNgrams.NgramsType (PatchMap NodeId NgramsTablePatch)
673 instance Serialise (PM.PatchMap NodeId NgramsTablePatch)
674 instance Serialise NgramsStatePatch
676 initMockRepo :: NgramsRepo
677 initMockRepo = Repo 1 s []
679 s = Map.singleton TableNgrams.NgramsTerms
680 $ Map.singleton 47254
682 [ (n ^. ne_ngrams, ngramsElementToRepo n) | n <- mockTable ^. _NgramsTable ]
684 data RepoEnv = RepoEnv
685 { _renv_var :: !(MVar NgramsRepo)
686 , _renv_saver :: !(IO ())
687 , _renv_lock :: !FileLock
693 class HasRepoVar env where
694 repoVar :: Getter env (MVar NgramsRepo)
696 instance HasRepoVar (MVar NgramsRepo) where
699 class HasRepoSaver env where
700 repoSaver :: Getter env (IO ())
702 class (HasRepoVar env, HasRepoSaver env) => HasRepo env where
703 repoEnv :: Getter env RepoEnv
705 instance HasRepo RepoEnv where
708 instance HasRepoVar RepoEnv where
711 instance HasRepoSaver RepoEnv where
712 repoSaver = renv_saver
714 type RepoCmdM env err m =
717 , HasConnectionPool env
722 type QueryParamR = QueryParam' '[Required, Strict]
726 instance Arbitrary NgramsRepoElement where
727 arbitrary = elements $ map ngramsElementToRepo ns
729 NgramsTable ns = mockTable
732 instance FromHttpApiData (Map TableNgrams.NgramsType (Versioned NgramsTableMap))
734 parseUrlPiece x = maybeToEither x (decode $ cs x)
737 ngramsTypeFromTabType :: TabType -> TableNgrams.NgramsType
738 ngramsTypeFromTabType tabType =
739 let lieu = "Garg.API.Ngrams: " :: Text in
741 Sources -> TableNgrams.Sources
742 Authors -> TableNgrams.Authors
743 Institutes -> TableNgrams.Institutes
744 Terms -> TableNgrams.NgramsTerms
745 _ -> panic $ lieu <> "No Ngrams for this tab"
746 -- TODO: This `panic` would disapear with custom NgramsType.
751 data UpdateTableNgramsCharts = UpdateTableNgramsCharts
752 { _utn_tab_type :: !TabType
753 , _utn_list_id :: !ListId
754 } deriving (Eq, Show, Generic)
756 makeLenses ''UpdateTableNgramsCharts
757 instance FromJSON UpdateTableNgramsCharts where
758 parseJSON = genericParseJSON $ jsonOptions "_utn_"
759 instance ToSchema UpdateTableNgramsCharts where
760 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_utn_")