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 Data.Map.Strict (Map)
24 import Data.Maybe (fromMaybe)
26 import Data.Patch.Class (Replace, replace, Action(act), Group, Applicable(..), Composable(..), Transformable(..),PairPatch(..), Patched, ConflictResolution, ConflictResolutionReplace,MaybePatch(Mod), unMod, old, new)
28 import Data.String (IsString, fromString)
29 import Data.Swagger hiding (version, patch)
30 import Data.Text (Text, pack, strip)
32 import Database.PostgreSQL.Simple.FromField (FromField, fromField, ResultError(ConversionFailed), returnError)
33 import GHC.Generics (Generic)
34 import Gargantext.Core.Text (size)
35 import Gargantext.Core.Types (ListType(..), ListId, NodeId)
36 import Gargantext.Core.Types (TODO)
37 import Gargantext.Core.Utils.Prefix (unPrefix, unPrefixUntagged, unPrefixSwagger, wellNamedSchema)
38 import Gargantext.Database.Prelude (fromField', CmdM', HasConnectionPool, HasConfig)
39 import Gargantext.Prelude
40 import Gargantext.Prelude.Crypto.Hash (IsHashable(..))
41 import Protolude (maybeToEither)
42 import Servant hiding (Patch)
43 import Servant.Job.Utils (jsonOptions)
44 import System.FileLock (FileLock)
45 import Test.QuickCheck (elements, frequency)
46 import Test.QuickCheck.Arbitrary (Arbitrary, arbitrary)
47 import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap
48 import qualified Data.List as List
49 import qualified Data.Map.Strict as Map
50 import qualified Data.Map.Strict.Patch as PM
51 import qualified Data.Set as Set
52 import qualified Gargantext.Database.Query.Table.Ngrams as TableNgrams
54 ------------------------------------------------------------------------
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 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)
128 instance IsHashable NgramsTerm where
129 hash (NgramsTerm t) = hash t
131 instance Monoid NgramsTerm where
132 mempty = NgramsTerm ""
134 instance FromJSONKey NgramsTerm where
135 fromJSONKey = FromJSONKeyTextParser $ \t -> pure $ NgramsTerm $ strip t
137 instance IsString NgramsTerm where
138 fromString s = NgramsTerm $ pack s
140 instance FromField NgramsTerm
142 fromField field mb = do
143 v <- fromField field mb
145 Success a -> pure $ NgramsTerm $ strip a
146 Error _err -> returnError ConversionFailed field
147 $ List.intercalate " " [ "cannot parse hyperdata for JSON: "
151 data RootParent = RootParent
152 { _rp_root :: NgramsTerm
153 , _rp_parent :: NgramsTerm
155 deriving (Ord, Eq, Show, Generic)
157 deriveJSON (unPrefix "_rp_") ''RootParent
158 makeLenses ''RootParent
160 data NgramsRepoElement = NgramsRepoElement
162 , _nre_list :: !ListType
163 , _nre_root :: !(Maybe NgramsTerm)
164 , _nre_parent :: !(Maybe NgramsTerm)
165 , _nre_children :: !(MSet NgramsTerm)
167 deriving (Ord, Eq, Show, Generic)
169 deriveJSON (unPrefix "_nre_") ''NgramsRepoElement
171 -- if ngrams & not size => size
174 makeLenses ''NgramsRepoElement
176 instance ToSchema NgramsRepoElement where
177 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_nre_")
179 instance Serialise (MSet NgramsTerm)
180 instance Serialise NgramsRepoElement
183 NgramsElement { _ne_ngrams :: NgramsTerm
185 , _ne_list :: ListType
186 , _ne_occurrences :: Int
187 , _ne_root :: Maybe NgramsTerm
188 , _ne_parent :: Maybe NgramsTerm
189 , _ne_children :: MSet NgramsTerm
191 deriving (Ord, Eq, Show, Generic)
193 deriveJSON (unPrefix "_ne_") ''NgramsElement
194 makeLenses ''NgramsElement
196 mkNgramsElement :: NgramsTerm
201 mkNgramsElement ngrams list rp children =
202 NgramsElement ngrams (size (unNgramsTerm ngrams)) list 1 (_rp_root <$> rp) (_rp_parent <$> rp) children
204 newNgramsElement :: Maybe ListType -> NgramsTerm -> NgramsElement
205 newNgramsElement mayList ngrams =
206 mkNgramsElement ngrams (fromMaybe MapTerm mayList) Nothing mempty
208 instance ToSchema NgramsElement where
209 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_ne_")
210 instance Arbitrary NgramsElement where
211 arbitrary = elements [newNgramsElement Nothing "sport"]
214 ------------------------------------------------------------------------
215 newtype NgramsTable = NgramsTable [NgramsElement]
216 deriving (Ord, Eq, Generic, ToJSON, FromJSON, Show)
218 -- type NgramsList = NgramsTable
220 makePrisms ''NgramsTable
222 -- | Question: why these repetition of Type in this instance
223 -- may you document it please ?
224 instance Each NgramsTable NgramsTable NgramsElement NgramsElement where
225 each = _NgramsTable . each
228 -- | TODO Check N and Weight
230 toNgramsElement :: [NgramsTableData] -> [NgramsElement]
231 toNgramsElement ns = map toNgramsElement' ns
233 toNgramsElement' (NgramsTableData _ p t _ lt w) = NgramsElement t lt' (round w) p' c'
237 Just x -> lookup x mapParent
238 c' = maybe mempty identity $ lookup t mapChildren
239 lt' = maybe (panic "API.Ngrams: listypeId") identity lt
241 mapParent :: Map Int Text
242 mapParent = Map.fromListWith (<>) $ map (\(NgramsTableData i _ t _ _ _) -> (i,t)) ns
244 mapChildren :: Map Text (Set Text)
245 mapChildren = Map.mapKeys (\i -> (maybe (panic "API.Ngrams.mapChildren: ParentId with no Terms: Impossible") identity $ lookup i mapParent))
246 $ Map.fromListWith (<>)
247 $ map (first fromJust)
248 $ filter (isJust . fst)
249 $ map (\(NgramsTableData _ p t _ _ _) -> (p, Set.singleton t)) ns
252 mockTable :: NgramsTable
253 mockTable = NgramsTable
254 [ mkNgramsElement "animal" MapTerm Nothing (mSetFromList ["dog", "cat"])
255 , mkNgramsElement "cat" MapTerm (rp "animal") mempty
256 , mkNgramsElement "cats" StopTerm Nothing mempty
257 , mkNgramsElement "dog" MapTerm (rp "animal") (mSetFromList ["dogs"])
258 , mkNgramsElement "dogs" StopTerm (rp "dog") mempty
259 , mkNgramsElement "fox" MapTerm Nothing mempty
260 , mkNgramsElement "object" CandidateTerm Nothing mempty
261 , mkNgramsElement "nothing" StopTerm Nothing mempty
262 , mkNgramsElement "organic" MapTerm Nothing (mSetFromList ["flower"])
263 , mkNgramsElement "flower" MapTerm (rp "organic") mempty
264 , mkNgramsElement "moon" CandidateTerm Nothing mempty
265 , mkNgramsElement "sky" StopTerm Nothing mempty
268 rp n = Just $ RootParent n n
270 instance Arbitrary NgramsTable where
271 arbitrary = pure mockTable
273 instance ToSchema NgramsTable
275 ------------------------------------------------------------------------
276 type NgramsTableMap = Map NgramsTerm NgramsRepoElement
277 ------------------------------------------------------------------------
278 -- On the Client side:
279 --data Action = InGroup NgramsId NgramsId
280 -- | OutGroup NgramsId NgramsId
281 -- | SetListType NgramsId ListType
283 data PatchSet a = PatchSet
287 deriving (Eq, Ord, Show, Generic)
289 makeLenses ''PatchSet
290 makePrisms ''PatchSet
292 instance ToJSON a => ToJSON (PatchSet a) where
293 toJSON = genericToJSON $ unPrefix "_"
294 toEncoding = genericToEncoding $ unPrefix "_"
296 instance (Ord a, FromJSON a) => FromJSON (PatchSet a) where
297 parseJSON = genericParseJSON $ unPrefix "_"
300 instance (Ord a, Arbitrary a) => Arbitrary (PatchSet a) where
301 arbitrary = PatchSet <$> arbitrary <*> arbitrary
303 type instance Patched (PatchSet a) = Set a
305 type ConflictResolutionPatchSet a = SimpleConflictResolution' (Set a)
306 type instance ConflictResolution (PatchSet a) = ConflictResolutionPatchSet a
308 instance Ord a => Semigroup (PatchSet a) where
309 p <> q = PatchSet { _rem = (q ^. rem) `Set.difference` (p ^. add) <> p ^. rem
310 , _add = (q ^. add) `Set.difference` (p ^. rem) <> p ^. add
313 instance Ord a => Monoid (PatchSet a) where
314 mempty = PatchSet mempty mempty
316 instance Ord a => Group (PatchSet a) where
317 invert (PatchSet r a) = PatchSet a r
319 instance Ord a => Composable (PatchSet a) where
320 composable _ _ = undefined
322 instance Ord a => Action (PatchSet a) (Set a) where
323 act p source = (source `Set.difference` (p ^. rem)) <> p ^. add
325 instance Applicable (PatchSet a) (Set a) where
326 applicable _ _ = mempty
328 instance Ord a => Validity (PatchSet a) where
329 validate p = check (Set.disjoint (p ^. rem) (p ^. add)) "_rem and _add should be dijoint"
331 instance Ord a => Transformable (PatchSet a) where
332 transformable = undefined
334 conflicts _p _q = undefined
336 transformWith conflict p q = undefined conflict p q
338 instance ToSchema a => ToSchema (PatchSet a)
341 type AddRem = Replace (Maybe ())
343 instance Serialise AddRem
345 remPatch, addPatch :: AddRem
346 remPatch = replace (Just ()) Nothing
347 addPatch = replace Nothing (Just ())
349 isRem :: Replace (Maybe ()) -> Bool
350 isRem = (== remPatch)
352 type PatchMap = PM.PatchMap
354 newtype PatchMSet a = PatchMSet (PatchMap a AddRem)
355 deriving (Eq, Show, Generic, Validity, Semigroup, Monoid, Group,
356 Transformable, Composable)
358 unPatchMSet :: PatchMSet a -> PatchMap a AddRem
359 unPatchMSet (PatchMSet a) = a
361 type ConflictResolutionPatchMSet a = a -> ConflictResolutionReplace (Maybe ())
362 type instance ConflictResolution (PatchMSet a) = ConflictResolutionPatchMSet a
364 instance (Serialise a, Ord a) => Serialise (PatchMap a AddRem)
365 instance (Serialise a, Ord a) => Serialise (PatchMSet a)
367 -- TODO this breaks module abstraction
368 makePrisms ''PM.PatchMap
370 makePrisms ''PatchMSet
372 _PatchMSetIso :: Ord a => Iso' (PatchMSet a) (PatchSet a)
373 _PatchMSetIso = _PatchMSet . _PatchMap . iso f g . from _PatchSet
375 f :: Ord a => Map a (Replace (Maybe ())) -> (Set a, Set a)
376 f = Map.partition isRem >>> both %~ Map.keysSet
378 g :: Ord a => (Set a, Set a) -> Map a (Replace (Maybe ()))
379 g (rems, adds) = Map.fromSet (const remPatch) rems
380 <> Map.fromSet (const addPatch) adds
382 instance Ord a => Action (PatchMSet a) (MSet a) where
383 act (PatchMSet p) (MSet m) = MSet $ act p m
385 instance Ord a => Applicable (PatchMSet a) (MSet a) where
386 applicable (PatchMSet p) (MSet m) = applicable p m
388 instance (Ord a, ToJSON a) => ToJSON (PatchMSet a) where
389 toJSON = toJSON . view _PatchMSetIso
390 toEncoding = toEncoding . view _PatchMSetIso
392 instance (Ord a, FromJSON a) => FromJSON (PatchMSet a) where
393 parseJSON = fmap (_PatchMSetIso #) . parseJSON
395 instance (Ord a, Arbitrary a) => Arbitrary (PatchMSet a) where
396 arbitrary = (PatchMSet . PM.fromMap) <$> arbitrary
398 instance ToSchema a => ToSchema (PatchMSet a) where
400 declareNamedSchema _ = wellNamedSchema "" (Proxy :: Proxy TODO)
402 type instance Patched (PatchMSet a) = MSet a
404 instance (Eq a, Arbitrary a) => Arbitrary (Replace a) where
405 arbitrary = uncurry replace <$> arbitrary
406 -- If they happen to be equal then the patch is Keep.
408 instance ToSchema a => ToSchema (Replace a) where
409 declareNamedSchema (_ :: Proxy (Replace a)) = do
410 -- TODO Keep constructor is not supported here.
411 aSchema <- declareSchemaRef (Proxy :: Proxy a)
412 return $ NamedSchema (Just "Replace") $ mempty
413 & type_ ?~ SwaggerObject
415 InsOrdHashMap.fromList
419 & required .~ [ "old", "new" ]
422 = NgramsPatch { _patch_children :: !(PatchMSet NgramsTerm)
423 , _patch_list :: !(Replace ListType) -- TODO Map UserId ListType
425 | NgramsReplace { _patch_old :: !(Maybe NgramsRepoElement)
426 , _patch_new :: !(Maybe NgramsRepoElement)
428 deriving (Eq, Show, Generic)
430 -- The JSON encoding is untagged, this is OK since the field names are disjoints and thus the encoding is unambiguous.
431 -- TODO: the empty object should be accepted and treated as mempty.
432 deriveJSON (unPrefixUntagged "_") ''NgramsPatch
433 makeLenses ''NgramsPatch
435 -- TODO: This instance is simplified since we should either have the fields children and/or list
436 -- or the fields old and/or new.
437 instance ToSchema NgramsPatch where
438 declareNamedSchema _ = do
439 childrenSch <- declareSchemaRef (Proxy :: Proxy (PatchMSet NgramsTerm))
440 listSch <- declareSchemaRef (Proxy :: Proxy (Replace ListType))
441 nreSch <- declareSchemaRef (Proxy :: Proxy NgramsRepoElement)
442 return $ NamedSchema (Just "NgramsPatch") $ mempty
443 & type_ ?~ SwaggerObject
445 InsOrdHashMap.fromList
446 [ ("children", childrenSch)
452 instance Arbitrary NgramsPatch where
453 arbitrary = frequency [ (9, NgramsPatch <$> arbitrary <*> (replace <$> arbitrary <*> arbitrary))
454 , (1, NgramsReplace <$> arbitrary <*> arbitrary)
457 instance Serialise NgramsPatch
458 instance Serialise (Replace ListType)
460 instance Serialise ListType
462 type NgramsPatchIso =
463 MaybePatch NgramsRepoElement (PairPatch (PatchMSet NgramsTerm) (Replace ListType))
465 _NgramsPatch :: Iso' NgramsPatch NgramsPatchIso
466 _NgramsPatch = iso unwrap wrap
468 unwrap (NgramsPatch c l) = Mod $ PairPatch (c, l)
469 unwrap (NgramsReplace o n) = replace o n
472 Just (PairPatch (c, l)) -> NgramsPatch c l
473 Nothing -> NgramsReplace (x ^? old . _Just) (x ^? new . _Just)
475 instance Semigroup NgramsPatch where
476 p <> q = _NgramsPatch # (p ^. _NgramsPatch <> q ^. _NgramsPatch)
478 instance Monoid NgramsPatch where
479 mempty = _NgramsPatch # mempty
481 instance Validity NgramsPatch where
482 validate p = p ^. _NgramsPatch . to validate
484 instance Transformable NgramsPatch where
485 transformable p q = transformable (p ^. _NgramsPatch) (q ^. _NgramsPatch)
487 conflicts p q = conflicts (p ^. _NgramsPatch) (q ^. _NgramsPatch)
489 transformWith conflict p q = (_NgramsPatch # p', _NgramsPatch # q')
491 (p', q') = transformWith conflict (p ^. _NgramsPatch) (q ^. _NgramsPatch)
493 type ConflictResolutionNgramsPatch =
494 ( ConflictResolutionReplace (Maybe NgramsRepoElement)
495 , ( ConflictResolutionPatchMSet NgramsTerm
496 , ConflictResolutionReplace ListType
500 type instance ConflictResolution NgramsPatch =
501 ConflictResolutionNgramsPatch
503 type PatchedNgramsPatch = Maybe NgramsRepoElement
504 type instance Patched NgramsPatch = PatchedNgramsPatch
506 instance Applicable (PairPatch (PatchMSet NgramsTerm) (Replace ListType)) NgramsRepoElement where
507 applicable (PairPatch (c, l)) n = applicable c (n ^. nre_children) <> applicable l (n ^. nre_list)
509 instance Action (PairPatch (PatchMSet NgramsTerm) (Replace ListType)) NgramsRepoElement where
510 act (PairPatch (c, l)) = (nre_children %~ act c)
511 . (nre_list %~ act l)
513 instance Applicable NgramsPatch (Maybe NgramsRepoElement) where
514 applicable p = applicable (p ^. _NgramsPatch)
516 instance Action NgramsPatch (Maybe NgramsRepoElement) where
517 act p = act (p ^. _NgramsPatch)
519 newtype NgramsTablePatch = NgramsTablePatch (PatchMap NgramsTerm NgramsPatch)
520 deriving (Eq, Show, Generic, ToJSON, FromJSON, Semigroup, Monoid, Validity, Transformable)
522 instance Serialise NgramsTablePatch
523 instance Serialise (PatchMap NgramsTerm NgramsPatch)
525 instance FromField NgramsTablePatch
527 fromField = fromField'
529 instance FromField (PatchMap TableNgrams.NgramsType (PatchMap NodeId NgramsTablePatch))
531 fromField = fromField'
533 type instance ConflictResolution NgramsTablePatch =
534 NgramsTerm -> ConflictResolutionNgramsPatch
536 type PatchedNgramsTablePatch = Map NgramsTerm PatchedNgramsPatch
537 -- ~ Patched (PatchMap NgramsTerm NgramsPatch)
538 type instance Patched NgramsTablePatch = PatchedNgramsTablePatch
540 makePrisms ''NgramsTablePatch
541 instance ToSchema (PatchMap NgramsTerm NgramsPatch)
542 instance ToSchema NgramsTablePatch
544 instance Applicable NgramsTablePatch (Maybe NgramsTableMap) where
545 applicable p = applicable (p ^. _NgramsTablePatch)
548 ngramsElementToRepo :: NgramsElement -> NgramsRepoElement
550 (NgramsElement { _ne_size = s
564 ngramsElementFromRepo :: NgramsTerm -> NgramsRepoElement -> NgramsElement
565 ngramsElementFromRepo
574 NgramsElement { _ne_size = s
579 , _ne_ngrams = ngrams
580 , _ne_occurrences = panic $ "API.Ngrams._ne_occurrences"
582 -- Here we could use 0 if we want to avoid any `panic`.
583 -- It will not happen using getTableNgrams if
584 -- getOccByNgramsOnly provides a count of occurrences for
585 -- all the ngrams given.
589 reRootChildren :: NgramsTerm -> ReParent NgramsTerm
590 reRootChildren root ngram = do
591 nre <- use $ at ngram
592 forOf_ (_Just . nre_children . folded) nre $ \child -> do
593 at child . _Just . nre_root ?= root
594 reRootChildren root child
596 reParent :: Maybe RootParent -> ReParent NgramsTerm
597 reParent rp child = do
598 at child . _Just %= ( (nre_parent .~ (_rp_parent <$> rp))
599 . (nre_root .~ (_rp_root <$> rp))
601 reRootChildren (fromMaybe child (rp ^? _Just . rp_root)) child
603 reParentAddRem :: RootParent -> NgramsTerm -> ReParent AddRem
604 reParentAddRem rp child p =
605 reParent (if isRem p then Nothing else Just rp) child
607 reParentNgramsPatch :: NgramsTerm -> ReParent NgramsPatch
608 reParentNgramsPatch parent ngramsPatch = do
609 root_of_parent <- use (at parent . _Just . nre_root)
611 root = fromMaybe parent root_of_parent
612 rp = RootParent { _rp_root = root, _rp_parent = parent }
613 itraverse_ (reParentAddRem rp) (ngramsPatch ^. patch_children . _PatchMSet . _PatchMap)
614 -- TODO FoldableWithIndex/TraversableWithIndex for PatchMap
616 reParentNgramsTablePatch :: ReParent NgramsTablePatch
617 reParentNgramsTablePatch p = itraverse_ reParentNgramsPatch (p ^. _NgramsTablePatch. _PatchMap)
618 -- TODO FoldableWithIndex/TraversableWithIndex for PatchMap
620 ------------------------------------------------------------------------
622 instance Action NgramsTablePatch (Maybe NgramsTableMap) where
624 fmap (execState (reParentNgramsTablePatch p)) .
625 act (p ^. _NgramsTablePatch)
627 instance Arbitrary NgramsTablePatch where
628 arbitrary = NgramsTablePatch <$> PM.fromMap <$> arbitrary
630 -- Should it be less than an Lens' to preserve PatchMap's abstraction.
631 -- ntp_ngrams_patches :: Lens' NgramsTablePatch (Map NgramsTerm NgramsPatch)
632 -- ntp_ngrams_patches = _NgramsTablePatch . undefined
634 type ReParent a = forall m. MonadState NgramsTableMap m => a -> m ()
636 ------------------------------------------------------------------------
639 data Versioned a = Versioned
640 { _v_version :: Version
643 deriving (Generic, Show, Eq)
644 deriveJSON (unPrefix "_v_") ''Versioned
645 makeLenses ''Versioned
646 instance (Typeable a, ToSchema a) => ToSchema (Versioned a) where
647 declareNamedSchema = wellNamedSchema "_v_"
648 instance Arbitrary a => Arbitrary (Versioned a) where
649 arbitrary = Versioned 1 <$> arbitrary -- TODO 1 is constant so far
650 ------------------------------------------------------------------------
653 data VersionedWithCount a = VersionedWithCount
654 { _vc_version :: Version
658 deriving (Generic, Show, Eq)
659 deriveJSON (unPrefix "_vc_") ''VersionedWithCount
660 makeLenses ''VersionedWithCount
661 instance (Typeable a, ToSchema a) => ToSchema (VersionedWithCount a) where
662 declareNamedSchema = wellNamedSchema "_vc_"
663 instance Arbitrary a => Arbitrary (VersionedWithCount a) where
664 arbitrary = VersionedWithCount 1 1 <$> arbitrary -- TODO 1 is constant so far
666 toVersionedWithCount :: Count -> Versioned a -> VersionedWithCount a
667 toVersionedWithCount count (Versioned version data_) = VersionedWithCount version count data_
668 ------------------------------------------------------------------------
670 { _r_version :: !Version
673 -- first patch in the list is the most recent
675 deriving (Generic, Show)
677 instance (FromJSON s, FromJSON p) => FromJSON (Repo s p) where
678 parseJSON = genericParseJSON $ unPrefix "_r_"
680 instance (ToJSON s, ToJSON p) => ToJSON (Repo s p) where
681 toJSON = genericToJSON $ unPrefix "_r_"
682 toEncoding = genericToEncoding $ unPrefix "_r_"
684 instance (Serialise s, Serialise p) => Serialise (Repo s p)
688 initRepo :: Monoid s => Repo s p
689 initRepo = Repo 1 mempty []
691 type NgramsRepo = Repo NgramsState NgramsStatePatch
692 type NgramsState = Map TableNgrams.NgramsType (Map NodeId NgramsTableMap)
693 type NgramsStatePatch = PatchMap TableNgrams.NgramsType (PatchMap NodeId NgramsTablePatch)
695 instance Serialise (PM.PatchMap NodeId NgramsTablePatch)
696 instance Serialise NgramsStatePatch
698 initMockRepo :: NgramsRepo
699 initMockRepo = Repo 1 s []
701 s = Map.singleton TableNgrams.NgramsTerms
702 $ Map.singleton 47254
704 [ (n ^. ne_ngrams, ngramsElementToRepo n) | n <- mockTable ^. _NgramsTable ]
706 data RepoEnv = RepoEnv
707 { _renv_var :: !(MVar NgramsRepo)
708 , _renv_saver :: !(IO ())
709 , _renv_lock :: !FileLock
715 class HasRepoVar env where
716 repoVar :: Getter env (MVar NgramsRepo)
718 instance HasRepoVar (MVar NgramsRepo) where
721 class HasRepoSaver env where
722 repoSaver :: Getter env (IO ())
724 class (HasRepoVar env, HasRepoSaver env) => HasRepo env where
725 repoEnv :: Getter env RepoEnv
727 instance HasRepo RepoEnv where
730 instance HasRepoVar RepoEnv where
733 instance HasRepoSaver RepoEnv where
734 repoSaver = renv_saver
736 type RepoCmdM env err m =
739 , HasConnectionPool env
744 type QueryParamR = QueryParam' '[Required, Strict]
748 instance Arbitrary NgramsRepoElement where
749 arbitrary = elements $ map ngramsElementToRepo ns
751 NgramsTable ns = mockTable
753 instance FromHttpApiData (Map TableNgrams.NgramsType (Versioned NgramsTableMap))
755 parseUrlPiece x = maybeToEither x (decode $ cs x)
757 ngramsTypeFromTabType :: TabType -> TableNgrams.NgramsType
758 ngramsTypeFromTabType tabType =
759 let lieu = "Garg.API.Ngrams: " :: Text in
761 Sources -> TableNgrams.Sources
762 Authors -> TableNgrams.Authors
763 Institutes -> TableNgrams.Institutes
764 Terms -> TableNgrams.NgramsTerms
765 _ -> panic $ lieu <> "No Ngrams for this tab"
766 -- TODO: This `panic` would disapear with custom NgramsType.
771 data UpdateTableNgramsCharts = UpdateTableNgramsCharts
772 { _utn_tab_type :: !TabType
773 , _utn_list_id :: !ListId
774 } deriving (Eq, Show, Generic)
776 makeLenses ''UpdateTableNgramsCharts
777 instance FromJSON UpdateTableNgramsCharts where
778 parseJSON = genericParseJSON $ jsonOptions "_utn_"
780 instance ToJSON UpdateTableNgramsCharts where
781 toJSON = genericToJSON $ jsonOptions "_utn_"
783 instance ToSchema UpdateTableNgramsCharts where
784 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_utn_")
786 ------------------------------------------------------------------------
787 type NgramsList = (Map TableNgrams.NgramsType (Versioned NgramsTableMap))