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)
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
350 newtype PatchMSet a = PatchMSet (PatchMap a AddRem)
351 deriving (Eq, Show, Generic, Validity, Semigroup, Monoid, Group,
352 Transformable, Composable)
354 type ConflictResolutionPatchMSet a = a -> ConflictResolutionReplace (Maybe ())
355 type instance ConflictResolution (PatchMSet a) = ConflictResolutionPatchMSet a
357 instance (Serialise a, Ord a) => Serialise (PatchMap a AddRem)
358 instance (Serialise a, Ord a) => Serialise (PatchMSet a)
360 -- TODO this breaks module abstraction
361 makePrisms ''PM.PatchMap
363 makePrisms ''PatchMSet
365 _PatchMSetIso :: Ord a => Iso' (PatchMSet a) (PatchSet a)
366 _PatchMSetIso = _PatchMSet . _PatchMap . iso f g . from _PatchSet
368 f :: Ord a => Map a (Replace (Maybe ())) -> (Set a, Set a)
369 f = Map.partition isRem >>> both %~ Map.keysSet
371 g :: Ord a => (Set a, Set a) -> Map a (Replace (Maybe ()))
372 g (rems, adds) = Map.fromSet (const remPatch) rems
373 <> Map.fromSet (const addPatch) adds
375 instance Ord a => Action (PatchMSet a) (MSet a) where
376 act (PatchMSet p) (MSet m) = MSet $ act p m
378 instance Ord a => Applicable (PatchMSet a) (MSet a) where
379 applicable (PatchMSet p) (MSet m) = applicable p m
381 instance (Ord a, ToJSON a) => ToJSON (PatchMSet a) where
382 toJSON = toJSON . view _PatchMSetIso
383 toEncoding = toEncoding . view _PatchMSetIso
385 instance (Ord a, FromJSON a) => FromJSON (PatchMSet a) where
386 parseJSON = fmap (_PatchMSetIso #) . parseJSON
388 instance (Ord a, Arbitrary a) => Arbitrary (PatchMSet a) where
389 arbitrary = (PatchMSet . PM.fromMap) <$> arbitrary
391 instance ToSchema a => ToSchema (PatchMSet a) where
393 declareNamedSchema _ = wellNamedSchema "" (Proxy :: Proxy TODO)
395 type instance Patched (PatchMSet a) = MSet a
397 instance (Eq a, Arbitrary a) => Arbitrary (Replace a) where
398 arbitrary = uncurry replace <$> arbitrary
399 -- If they happen to be equal then the patch is Keep.
401 instance ToSchema a => ToSchema (Replace a) where
402 declareNamedSchema (_ :: Proxy (Replace a)) = do
403 -- TODO Keep constructor is not supported here.
404 aSchema <- declareSchemaRef (Proxy :: Proxy a)
405 return $ NamedSchema (Just "Replace") $ mempty
406 & type_ ?~ SwaggerObject
408 InsOrdHashMap.fromList
412 & required .~ [ "old", "new" ]
415 = NgramsPatch { _patch_children :: !(PatchMSet NgramsTerm)
416 , _patch_list :: !(Replace ListType) -- TODO Map UserId ListType
418 | NgramsReplace { _patch_old :: !(Maybe NgramsRepoElement)
419 , _patch_new :: !(Maybe NgramsRepoElement)
421 deriving (Eq, Show, Generic)
423 -- The JSON encoding is untagged, this is OK since the field names are disjoints and thus the encoding is unambiguous.
424 -- TODO: the empty object should be accepted and treated as mempty.
425 deriveJSON (unPrefixUntagged "_") ''NgramsPatch
426 makeLenses ''NgramsPatch
428 -- TODO: This instance is simplified since we should either have the fields children and/or list
429 -- or the fields old and/or new.
430 instance ToSchema NgramsPatch where
431 declareNamedSchema _ = do
432 childrenSch <- declareSchemaRef (Proxy :: Proxy (PatchMSet NgramsTerm))
433 listSch <- declareSchemaRef (Proxy :: Proxy (Replace ListType))
434 nreSch <- declareSchemaRef (Proxy :: Proxy NgramsRepoElement)
435 return $ NamedSchema (Just "NgramsPatch") $ mempty
436 & type_ ?~ SwaggerObject
438 InsOrdHashMap.fromList
439 [ ("children", childrenSch)
445 instance Arbitrary NgramsPatch where
446 arbitrary = frequency [ (9, NgramsPatch <$> arbitrary <*> (replace <$> arbitrary <*> arbitrary))
447 , (1, NgramsReplace <$> arbitrary <*> arbitrary)
450 instance Serialise NgramsPatch
451 instance Serialise (Replace ListType)
453 instance Serialise ListType
455 type NgramsPatchIso =
456 MaybePatch NgramsRepoElement (PairPatch (PatchMSet NgramsTerm) (Replace ListType))
458 _NgramsPatch :: Iso' NgramsPatch NgramsPatchIso
459 _NgramsPatch = iso unwrap wrap
461 unwrap (NgramsPatch c l) = Mod $ PairPatch (c, l)
462 unwrap (NgramsReplace o n) = replace o n
465 Just (PairPatch (c, l)) -> NgramsPatch c l
466 Nothing -> NgramsReplace (x ^? old . _Just) (x ^? new . _Just)
468 instance Semigroup NgramsPatch where
469 p <> q = _NgramsPatch # (p ^. _NgramsPatch <> q ^. _NgramsPatch)
471 instance Monoid NgramsPatch where
472 mempty = _NgramsPatch # mempty
474 instance Validity NgramsPatch where
475 validate p = p ^. _NgramsPatch . to validate
477 instance Transformable NgramsPatch where
478 transformable p q = transformable (p ^. _NgramsPatch) (q ^. _NgramsPatch)
480 conflicts p q = conflicts (p ^. _NgramsPatch) (q ^. _NgramsPatch)
482 transformWith conflict p q = (_NgramsPatch # p', _NgramsPatch # q')
484 (p', q') = transformWith conflict (p ^. _NgramsPatch) (q ^. _NgramsPatch)
486 type ConflictResolutionNgramsPatch =
487 ( ConflictResolutionReplace (Maybe NgramsRepoElement)
488 , ( ConflictResolutionPatchMSet NgramsTerm
489 , ConflictResolutionReplace ListType
493 type instance ConflictResolution NgramsPatch =
494 ConflictResolutionNgramsPatch
496 type PatchedNgramsPatch = Maybe NgramsRepoElement
497 type instance Patched NgramsPatch = PatchedNgramsPatch
499 instance Applicable (PairPatch (PatchMSet NgramsTerm) (Replace ListType)) NgramsRepoElement where
500 applicable (PairPatch (c, l)) n = applicable c (n ^. nre_children) <> applicable l (n ^. nre_list)
502 instance Action (PairPatch (PatchMSet NgramsTerm) (Replace ListType)) NgramsRepoElement where
503 act (PairPatch (c, l)) = (nre_children %~ act c)
504 . (nre_list %~ act l)
506 instance Applicable NgramsPatch (Maybe NgramsRepoElement) where
507 applicable p = applicable (p ^. _NgramsPatch)
509 instance Action NgramsPatch (Maybe NgramsRepoElement) where
510 act p = act (p ^. _NgramsPatch)
512 newtype NgramsTablePatch = NgramsTablePatch (PatchMap NgramsTerm NgramsPatch)
513 deriving (Eq, Show, Generic, ToJSON, FromJSON, Semigroup, Monoid, Validity, Transformable)
515 instance Serialise NgramsTablePatch
516 instance Serialise (PatchMap NgramsTerm NgramsPatch)
518 instance FromField NgramsTablePatch
520 fromField = fromField'
522 instance FromField (PatchMap TableNgrams.NgramsType (PatchMap NodeId NgramsTablePatch))
524 fromField = fromField'
526 type instance ConflictResolution NgramsTablePatch =
527 NgramsTerm -> ConflictResolutionNgramsPatch
529 type PatchedNgramsTablePatch = Map NgramsTerm PatchedNgramsPatch
530 -- ~ Patched (PatchMap NgramsTerm NgramsPatch)
531 type instance Patched NgramsTablePatch = PatchedNgramsTablePatch
533 makePrisms ''NgramsTablePatch
534 instance ToSchema (PatchMap NgramsTerm NgramsPatch)
535 instance ToSchema NgramsTablePatch
537 instance Applicable NgramsTablePatch (Maybe NgramsTableMap) where
538 applicable p = applicable (p ^. _NgramsTablePatch)
541 ngramsElementToRepo :: NgramsElement -> NgramsRepoElement
543 (NgramsElement { _ne_size = s
557 ngramsElementFromRepo :: NgramsTerm -> NgramsRepoElement -> NgramsElement
558 ngramsElementFromRepo
567 NgramsElement { _ne_size = s
572 , _ne_ngrams = ngrams
573 , _ne_occurrences = panic $ "API.Ngrams._ne_occurrences"
575 -- Here we could use 0 if we want to avoid any `panic`.
576 -- It will not happen using getTableNgrams if
577 -- getOccByNgramsOnly provides a count of occurrences for
578 -- all the ngrams given.
582 reRootChildren :: NgramsTerm -> ReParent NgramsTerm
583 reRootChildren root ngram = do
584 nre <- use $ at ngram
585 forOf_ (_Just . nre_children . folded) nre $ \child -> do
586 at child . _Just . nre_root ?= root
587 reRootChildren root child
589 reParent :: Maybe RootParent -> ReParent NgramsTerm
590 reParent rp child = do
591 at child . _Just %= ( (nre_parent .~ (_rp_parent <$> rp))
592 . (nre_root .~ (_rp_root <$> rp))
594 reRootChildren (fromMaybe child (rp ^? _Just . rp_root)) child
596 reParentAddRem :: RootParent -> NgramsTerm -> ReParent AddRem
597 reParentAddRem rp child p =
598 reParent (if isRem p then Nothing else Just rp) child
600 reParentNgramsPatch :: NgramsTerm -> ReParent NgramsPatch
601 reParentNgramsPatch parent ngramsPatch = do
602 root_of_parent <- use (at parent . _Just . nre_root)
604 root = fromMaybe parent root_of_parent
605 rp = RootParent { _rp_root = root, _rp_parent = parent }
606 itraverse_ (reParentAddRem rp) (ngramsPatch ^. patch_children . _PatchMSet . _PatchMap)
607 -- TODO FoldableWithIndex/TraversableWithIndex for PatchMap
609 reParentNgramsTablePatch :: ReParent NgramsTablePatch
610 reParentNgramsTablePatch p = itraverse_ reParentNgramsPatch (p ^. _NgramsTablePatch. _PatchMap)
611 -- TODO FoldableWithIndex/TraversableWithIndex for PatchMap
613 ------------------------------------------------------------------------
615 instance Action NgramsTablePatch (Maybe NgramsTableMap) where
617 fmap (execState (reParentNgramsTablePatch p)) .
618 act (p ^. _NgramsTablePatch)
620 instance Arbitrary NgramsTablePatch where
621 arbitrary = NgramsTablePatch <$> PM.fromMap <$> arbitrary
623 -- Should it be less than an Lens' to preserve PatchMap's abstraction.
624 -- ntp_ngrams_patches :: Lens' NgramsTablePatch (Map NgramsTerm NgramsPatch)
625 -- ntp_ngrams_patches = _NgramsTablePatch . undefined
627 type ReParent a = forall m. MonadState NgramsTableMap m => a -> m ()
629 ------------------------------------------------------------------------
632 data Versioned a = Versioned
633 { _v_version :: Version
636 deriving (Generic, Show, Eq)
637 deriveJSON (unPrefix "_v_") ''Versioned
638 makeLenses ''Versioned
639 instance (Typeable a, ToSchema a) => ToSchema (Versioned a) where
640 declareNamedSchema = wellNamedSchema "_v_"
641 instance Arbitrary a => Arbitrary (Versioned a) where
642 arbitrary = Versioned 1 <$> arbitrary -- TODO 1 is constant so far
644 ------------------------------------------------------------------------
646 { _r_version :: !Version
649 -- first patch in the list is the most recent
653 instance (FromJSON s, FromJSON p) => FromJSON (Repo s p) where
654 parseJSON = genericParseJSON $ unPrefix "_r_"
656 instance (ToJSON s, ToJSON p) => ToJSON (Repo s p) where
657 toJSON = genericToJSON $ unPrefix "_r_"
658 toEncoding = genericToEncoding $ unPrefix "_r_"
660 instance (Serialise s, Serialise p) => Serialise (Repo s p)
664 initRepo :: Monoid s => Repo s p
665 initRepo = Repo 1 mempty []
667 type NgramsRepo = Repo NgramsState NgramsStatePatch
668 type NgramsState = Map TableNgrams.NgramsType (Map NodeId NgramsTableMap)
669 type NgramsStatePatch = PatchMap TableNgrams.NgramsType (PatchMap NodeId NgramsTablePatch)
671 instance Serialise (PM.PatchMap NodeId NgramsTablePatch)
672 instance Serialise NgramsStatePatch
674 initMockRepo :: NgramsRepo
675 initMockRepo = Repo 1 s []
677 s = Map.singleton TableNgrams.NgramsTerms
678 $ Map.singleton 47254
680 [ (n ^. ne_ngrams, ngramsElementToRepo n) | n <- mockTable ^. _NgramsTable ]
682 data RepoEnv = RepoEnv
683 { _renv_var :: !(MVar NgramsRepo)
684 , _renv_saver :: !(IO ())
685 , _renv_lock :: !FileLock
691 class HasRepoVar env where
692 repoVar :: Getter env (MVar NgramsRepo)
694 instance HasRepoVar (MVar NgramsRepo) where
697 class HasRepoSaver env where
698 repoSaver :: Getter env (IO ())
700 class (HasRepoVar env, HasRepoSaver env) => HasRepo env where
701 repoEnv :: Getter env RepoEnv
703 instance HasRepo RepoEnv where
706 instance HasRepoVar RepoEnv where
709 instance HasRepoSaver RepoEnv where
710 repoSaver = renv_saver
712 type RepoCmdM env err m =
715 , HasConnectionPool env
720 type QueryParamR = QueryParam' '[Required, Strict]
724 instance Arbitrary NgramsRepoElement where
725 arbitrary = elements $ map ngramsElementToRepo ns
727 NgramsTable ns = mockTable
730 instance FromHttpApiData (Map TableNgrams.NgramsType (Versioned NgramsTableMap))
732 parseUrlPiece x = maybeToEither x (decode $ cs x)
735 ngramsTypeFromTabType :: TabType -> TableNgrams.NgramsType
736 ngramsTypeFromTabType tabType =
737 let lieu = "Garg.API.Ngrams: " :: Text in
739 Sources -> TableNgrams.Sources
740 Authors -> TableNgrams.Authors
741 Institutes -> TableNgrams.Institutes
742 Terms -> TableNgrams.NgramsTerms
743 _ -> panic $ lieu <> "No Ngrams for this tab"
744 -- TODO: This `panic` would disapear with custom NgramsType.
749 data UpdateTableNgramsCharts = UpdateTableNgramsCharts
750 { _utn_tab_type :: !TabType
751 , _utn_list_id :: !ListId
752 } deriving (Eq, Show, Generic)
754 makeLenses ''UpdateTableNgramsCharts
755 instance FromJSON UpdateTableNgramsCharts where
756 parseJSON = genericParseJSON $ jsonOptions "_utn_"
757 instance ToSchema UpdateTableNgramsCharts where
758 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_utn_")