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.Lens (makeLenses, makePrisms, Iso', iso, from, (.~), (?=), (#), to, folded, {-withIndex, ifolded,-} view, use, (^.), (^?), (%~), (.~), (%=), at, _Just, Each(..), itraverse_, both, forOf_, (?~))
15 import Control.Monad.State
16 import Data.Aeson hiding ((.=))
17 import Data.Aeson.TH (deriveJSON)
18 import Data.Either (Either(..))
20 import Data.Hashable (Hashable)
21 import Data.Map.Strict (Map)
22 import Data.Maybe (fromMaybe)
24 import Data.Patch.Class (Replace, replace, Action(act), Group, Applicable(..), Composable(..), Transformable(..), PairPatch(..), Patched, ConflictResolution, ConflictResolutionReplace, MaybePatch(Mod), unMod, old, new)
26 import Data.String (IsString, fromString)
27 import Data.Swagger hiding (version, patch)
28 import Data.Text (Text, pack, strip)
30 import Database.PostgreSQL.Simple.FromField (FromField, fromField, ResultError(ConversionFailed), returnError)
31 import GHC.Generics (Generic)
32 import Gargantext.Core.Text (size)
33 import Gargantext.Core.Types (ListType(..), ListId, NodeId, TODO)
34 import Gargantext.Core.Utils.Prefix (unPrefix, unPrefixUntagged, unPrefixSwagger, wellNamedSchema)
35 import Gargantext.Database.Prelude (fromField', HasConnectionPool, HasConfig, CmdM')
36 import Gargantext.Prelude
37 import Gargantext.Prelude.Crypto.Hash (IsHashable(..))
38 import Protolude (maybeToEither)
39 import Servant hiding (Patch)
40 import Servant.Job.Utils (jsonOptions)
41 -- import System.FileLock (FileLock)
42 import Test.QuickCheck (elements, frequency)
43 import Test.QuickCheck.Arbitrary (Arbitrary, arbitrary)
44 import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap
45 import qualified Data.List as List
46 import qualified Data.Map.Strict as Map
47 import qualified Data.Map.Strict.Patch as PM
48 import qualified Data.Set as Set
49 import qualified Gargantext.Database.Query.Table.Ngrams as TableNgrams
51 ------------------------------------------------------------------------
53 type QueryParamR = QueryParam' '[Required, Strict]
55 ------------------------------------------------------------------------
56 --data FacetFormat = Table | Chart
57 data TabType = Docs | Trash | MoreFav | MoreTrash
58 | Terms | Sources | Authors | Institutes
60 deriving (Bounded, Enum, Eq, Generic, Ord, Show)
63 instance Hashable TabType
65 instance FromHttpApiData TabType
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 ToParamSchema TabType
81 instance ToJSON TabType
82 instance FromJSON TabType
83 instance ToSchema TabType
84 instance Arbitrary TabType where
85 arbitrary = elements [minBound .. maxBound]
86 instance FromJSONKey TabType where
87 fromJSONKey = genericFromJSONKey defaultJSONKeyOptions
88 instance ToJSONKey TabType where
89 toJSONKey = genericToJSONKey defaultJSONKeyOptions
91 newtype MSet a = MSet (Map a ())
92 deriving (Eq, Ord, Show, Generic, Arbitrary, Semigroup, Monoid)
94 instance ToJSON a => ToJSON (MSet a) where
95 toJSON (MSet m) = toJSON (Map.keys m)
96 toEncoding (MSet m) = toEncoding (Map.keys m)
98 mSetFromSet :: Set a -> MSet a
99 mSetFromSet = MSet . Map.fromSet (const ())
101 mSetFromList :: Ord a => [a] -> MSet a
102 mSetFromList = MSet . Map.fromList . map (\x -> (x, ()))
104 -- mSetToSet :: Ord a => MSet a -> Set a
105 -- mSetToSet (MSet a) = Set.fromList ( Map.keys a)
106 mSetToSet :: Ord a => MSet a -> Set a
107 mSetToSet = Set.fromList . mSetToList
109 mSetToList :: MSet a -> [a]
110 mSetToList (MSet a) = Map.keys a
112 instance Foldable MSet where
113 foldMap f (MSet m) = Map.foldMapWithKey (\k _ -> f k) m
115 instance (Ord a, FromJSON a) => FromJSON (MSet a) where
116 parseJSON = fmap mSetFromList . parseJSON
118 instance (ToJSONKey a, ToSchema a) => ToSchema (MSet a) where
120 declareNamedSchema _ = wellNamedSchema "" (Proxy :: Proxy TODO)
122 ------------------------------------------------------------------------
123 newtype NgramsTerm = NgramsTerm { unNgramsTerm :: Text }
124 deriving (Ord, Eq, Show, Generic, ToJSONKey, ToJSON, FromJSON, Semigroup, Arbitrary, Serialise, ToSchema, Hashable)
126 instance IsHashable NgramsTerm where
127 hash (NgramsTerm t) = hash t
129 instance Monoid NgramsTerm where
130 mempty = NgramsTerm ""
132 instance FromJSONKey NgramsTerm where
133 fromJSONKey = FromJSONKeyTextParser $ \t -> pure $ NgramsTerm $ strip t
135 instance IsString NgramsTerm where
136 fromString s = NgramsTerm $ pack s
138 instance FromField NgramsTerm
140 fromField field mb = do
141 v <- fromField field mb
143 Success a -> pure $ NgramsTerm $ strip a
144 Error _err -> returnError ConversionFailed field
145 $ List.intercalate " " [ "cannot parse hyperdata for JSON: "
149 data RootParent = RootParent
150 { _rp_root :: NgramsTerm
151 , _rp_parent :: NgramsTerm
153 deriving (Ord, Eq, Show, Generic)
155 deriveJSON (unPrefix "_rp_") ''RootParent
156 makeLenses ''RootParent
158 data NgramsRepoElement = NgramsRepoElement
160 , _nre_list :: !ListType
161 , _nre_root :: !(Maybe NgramsTerm)
162 , _nre_parent :: !(Maybe NgramsTerm)
163 , _nre_children :: !(MSet NgramsTerm)
165 deriving (Ord, Eq, Show, Generic)
167 deriveJSON (unPrefix "_nre_") ''NgramsRepoElement
169 -- if ngrams & not size => size
172 makeLenses ''NgramsRepoElement
174 instance ToSchema NgramsRepoElement where
175 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_nre_")
177 instance Serialise (MSet NgramsTerm)
178 instance Serialise NgramsRepoElement
181 NgramsElement { _ne_ngrams :: NgramsTerm
183 , _ne_list :: ListType
184 , _ne_occurrences :: Int
185 , _ne_root :: Maybe NgramsTerm
186 , _ne_parent :: Maybe NgramsTerm
187 , _ne_children :: MSet NgramsTerm
189 deriving (Ord, Eq, Show, Generic)
191 deriveJSON (unPrefix "_ne_") ''NgramsElement
192 makeLenses ''NgramsElement
194 mkNgramsElement :: NgramsTerm
199 mkNgramsElement ngrams list rp children =
200 NgramsElement ngrams (size (unNgramsTerm ngrams)) list 1 (_rp_root <$> rp) (_rp_parent <$> rp) children
202 newNgramsElement :: Maybe ListType -> NgramsTerm -> NgramsElement
203 newNgramsElement mayList ngrams =
204 mkNgramsElement ngrams (fromMaybe MapTerm mayList) Nothing mempty
206 instance ToSchema NgramsElement where
207 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_ne_")
208 instance Arbitrary NgramsElement where
209 arbitrary = elements [newNgramsElement Nothing "sport"]
212 ------------------------------------------------------------------------
213 newtype NgramsTable = NgramsTable [NgramsElement]
214 deriving (Ord, Eq, Generic, ToJSON, FromJSON, Show)
216 -- type NgramsList = NgramsTable
218 makePrisms ''NgramsTable
220 -- | Question: why these repetition of Type in this instance
221 -- may you document it please ?
222 instance Each NgramsTable NgramsTable NgramsElement NgramsElement where
223 each = _NgramsTable . each
226 -- | TODO Check N and Weight
228 toNgramsElement :: [NgramsTableData] -> [NgramsElement]
229 toNgramsElement ns = map toNgramsElement' ns
231 toNgramsElement' (NgramsTableData _ p t _ lt w) = NgramsElement t lt' (round w) p' c'
235 Just x -> lookup x mapParent
236 c' = maybe mempty identity $ lookup t mapChildren
237 lt' = maybe (panic "API.Ngrams: listypeId") identity lt
239 mapParent :: Map Int Text
240 mapParent = Map.fromListWith (<>) $ map (\(NgramsTableData i _ t _ _ _) -> (i,t)) ns
242 mapChildren :: Map Text (Set Text)
243 mapChildren = Map.mapKeys (\i -> (maybe (panic "API.Ngrams.mapChildren: ParentId with no Terms: Impossible") identity $ lookup i mapParent))
244 $ Map.fromListWith (<>)
245 $ map (first fromJust)
246 $ filter (isJust . fst)
247 $ map (\(NgramsTableData _ p t _ _ _) -> (p, Set.singleton t)) ns
250 mockTable :: NgramsTable
251 mockTable = NgramsTable
252 [ mkNgramsElement "animal" MapTerm Nothing (mSetFromList ["dog", "cat"])
253 , mkNgramsElement "cat" MapTerm (rp "animal") mempty
254 , mkNgramsElement "cats" StopTerm Nothing mempty
255 , mkNgramsElement "dog" MapTerm (rp "animal") (mSetFromList ["dogs"])
256 , mkNgramsElement "dogs" StopTerm (rp "dog") mempty
257 , mkNgramsElement "fox" MapTerm Nothing mempty
258 , mkNgramsElement "object" CandidateTerm Nothing mempty
259 , mkNgramsElement "nothing" StopTerm Nothing mempty
260 , mkNgramsElement "organic" MapTerm Nothing (mSetFromList ["flower"])
261 , mkNgramsElement "flower" MapTerm (rp "organic") mempty
262 , mkNgramsElement "moon" CandidateTerm Nothing mempty
263 , mkNgramsElement "sky" StopTerm Nothing mempty
266 rp n = Just $ RootParent n n
268 instance Arbitrary NgramsTable where
269 arbitrary = pure mockTable
271 instance ToSchema NgramsTable
273 ------------------------------------------------------------------------
274 type NgramsTableMap = Map NgramsTerm NgramsRepoElement
275 ------------------------------------------------------------------------
276 -- On the Client side:
277 --data Action = InGroup NgramsId NgramsId
278 -- | OutGroup NgramsId NgramsId
279 -- | SetListType NgramsId ListType
281 data PatchSet a = PatchSet
285 deriving (Eq, Ord, Show, Generic)
287 makeLenses ''PatchSet
288 makePrisms ''PatchSet
290 instance ToJSON a => ToJSON (PatchSet a) where
291 toJSON = genericToJSON $ unPrefix "_"
292 toEncoding = genericToEncoding $ unPrefix "_"
294 instance (Ord a, FromJSON a) => FromJSON (PatchSet a) where
295 parseJSON = genericParseJSON $ unPrefix "_"
298 instance (Ord a, Arbitrary a) => Arbitrary (PatchSet a) where
299 arbitrary = PatchSet <$> arbitrary <*> arbitrary
301 type instance Patched (PatchSet a) = Set a
303 type ConflictResolutionPatchSet a = SimpleConflictResolution' (Set a)
304 type instance ConflictResolution (PatchSet a) = ConflictResolutionPatchSet a
306 instance Ord a => Semigroup (PatchSet a) where
307 p <> q = PatchSet { _rem = (q ^. rem) `Set.difference` (p ^. add) <> p ^. rem
308 , _add = (q ^. add) `Set.difference` (p ^. rem) <> p ^. add
311 instance Ord a => Monoid (PatchSet a) where
312 mempty = PatchSet mempty mempty
314 instance Ord a => Group (PatchSet a) where
315 invert (PatchSet r a) = PatchSet a r
317 instance Ord a => Composable (PatchSet a) where
318 composable _ _ = undefined
320 instance Ord a => Action (PatchSet a) (Set a) where
321 act p source = (source `Set.difference` (p ^. rem)) <> p ^. add
323 instance Applicable (PatchSet a) (Set a) where
324 applicable _ _ = mempty
326 instance Ord a => Validity (PatchSet a) where
327 validate p = check (Set.disjoint (p ^. rem) (p ^. add)) "_rem and _add should be dijoint"
329 instance Ord a => Transformable (PatchSet a) where
330 transformable = undefined
332 conflicts _p _q = undefined
334 transformWith conflict p q = undefined conflict p q
336 instance ToSchema a => ToSchema (PatchSet a)
339 type AddRem = Replace (Maybe ())
341 instance Serialise AddRem
343 remPatch, addPatch :: AddRem
344 remPatch = replace (Just ()) Nothing
345 addPatch = replace Nothing (Just ())
347 isRem :: Replace (Maybe ()) -> Bool
348 isRem = (== remPatch)
350 type PatchMap = PM.PatchMap
352 newtype PatchMSet a = PatchMSet (PatchMap a AddRem)
353 deriving (Eq, Show, Generic, Validity, Semigroup, Monoid, Group,
354 Transformable, Composable)
356 unPatchMSet :: PatchMSet a -> PatchMap a AddRem
357 unPatchMSet (PatchMSet a) = a
359 type ConflictResolutionPatchMSet a = a -> ConflictResolutionReplace (Maybe ())
360 type instance ConflictResolution (PatchMSet a) = ConflictResolutionPatchMSet a
362 instance (Serialise a, Ord a) => Serialise (PatchMap a AddRem)
363 instance (Serialise a, Ord a) => Serialise (PatchMSet a)
365 -- TODO this breaks module abstraction
366 makePrisms ''PM.PatchMap
368 makePrisms ''PatchMSet
370 _PatchMSetIso :: Ord a => Iso' (PatchMSet a) (PatchSet a)
371 _PatchMSetIso = _PatchMSet . _PatchMap . iso f g . from _PatchSet
373 f :: Ord a => Map a (Replace (Maybe ())) -> (Set a, Set a)
374 f = Map.partition isRem >>> both %~ Map.keysSet
376 g :: Ord a => (Set a, Set a) -> Map a (Replace (Maybe ()))
377 g (rems, adds) = Map.fromSet (const remPatch) rems
378 <> Map.fromSet (const addPatch) adds
380 instance Ord a => Action (PatchMSet a) (MSet a) where
381 act (PatchMSet p) (MSet m) = MSet $ act p m
383 instance Ord a => Applicable (PatchMSet a) (MSet a) where
384 applicable (PatchMSet p) (MSet m) = applicable p m
386 instance (Ord a, ToJSON a) => ToJSON (PatchMSet a) where
387 toJSON = toJSON . view _PatchMSetIso
388 toEncoding = toEncoding . view _PatchMSetIso
390 instance (Ord a, FromJSON a) => FromJSON (PatchMSet a) where
391 parseJSON = fmap (_PatchMSetIso #) . parseJSON
393 instance (Ord a, Arbitrary a) => Arbitrary (PatchMSet a) where
394 arbitrary = (PatchMSet . PM.fromMap) <$> arbitrary
396 instance ToSchema a => ToSchema (PatchMSet a) where
398 declareNamedSchema _ = wellNamedSchema "" (Proxy :: Proxy TODO)
400 type instance Patched (PatchMSet a) = MSet a
402 instance (Eq a, Arbitrary a) => Arbitrary (Replace a) where
403 arbitrary = uncurry replace <$> arbitrary
404 -- If they happen to be equal then the patch is Keep.
406 instance ToSchema a => ToSchema (Replace a) where
407 declareNamedSchema (_ :: Proxy (Replace a)) = do
408 -- TODO Keep constructor is not supported here.
409 aSchema <- declareSchemaRef (Proxy :: Proxy a)
410 return $ NamedSchema (Just "Replace") $ mempty
411 & type_ ?~ SwaggerObject
413 InsOrdHashMap.fromList
417 & required .~ [ "old", "new" ]
420 = NgramsPatch { _patch_children :: !(PatchMSet NgramsTerm)
421 , _patch_list :: !(Replace ListType) -- TODO Map UserId ListType
423 | NgramsReplace { _patch_old :: !(Maybe NgramsRepoElement)
424 , _patch_new :: !(Maybe NgramsRepoElement)
426 deriving (Eq, Show, Generic)
428 -- The JSON encoding is untagged, this is OK since the field names are disjoints and thus the encoding is unambiguous.
429 -- TODO: the empty object should be accepted and treated as mempty.
430 deriveJSON (unPrefixUntagged "_") ''NgramsPatch
431 makeLenses ''NgramsPatch
433 -- TODO: This instance is simplified since we should either have the fields children and/or list
434 -- or the fields old and/or new.
435 instance ToSchema NgramsPatch where
436 declareNamedSchema _ = do
437 childrenSch <- declareSchemaRef (Proxy :: Proxy (PatchMSet NgramsTerm))
438 listSch <- declareSchemaRef (Proxy :: Proxy (Replace ListType))
439 nreSch <- declareSchemaRef (Proxy :: Proxy NgramsRepoElement)
440 return $ NamedSchema (Just "NgramsPatch") $ mempty
441 & type_ ?~ SwaggerObject
443 InsOrdHashMap.fromList
444 [ ("children", childrenSch)
450 instance Arbitrary NgramsPatch where
451 arbitrary = frequency [ (9, NgramsPatch <$> arbitrary <*> (replace <$> arbitrary <*> arbitrary))
452 , (1, NgramsReplace <$> arbitrary <*> arbitrary)
455 instance Serialise NgramsPatch
456 instance Serialise (Replace ListType)
458 instance Serialise ListType
460 type NgramsPatchIso =
461 MaybePatch NgramsRepoElement (PairPatch (PatchMSet NgramsTerm) (Replace ListType))
463 _NgramsPatch :: Iso' NgramsPatch NgramsPatchIso
464 _NgramsPatch = iso unwrap wrap
466 unwrap (NgramsPatch c l) = Mod $ PairPatch (c, l)
467 unwrap (NgramsReplace o n) = replace o n
470 Just (PairPatch (c, l)) -> NgramsPatch c l
471 Nothing -> NgramsReplace (x ^? old . _Just) (x ^? new . _Just)
473 instance Semigroup NgramsPatch where
474 p <> q = _NgramsPatch # (p ^. _NgramsPatch <> q ^. _NgramsPatch)
476 instance Monoid NgramsPatch where
477 mempty = _NgramsPatch # mempty
479 instance Validity NgramsPatch where
480 validate p = p ^. _NgramsPatch . to validate
482 instance Transformable NgramsPatch where
483 transformable p q = transformable (p ^. _NgramsPatch) (q ^. _NgramsPatch)
485 conflicts p q = conflicts (p ^. _NgramsPatch) (q ^. _NgramsPatch)
487 transformWith conflict p q = (_NgramsPatch # p', _NgramsPatch # q')
489 (p', q') = transformWith conflict (p ^. _NgramsPatch) (q ^. _NgramsPatch)
491 type ConflictResolutionNgramsPatch =
492 ( ConflictResolutionReplace (Maybe NgramsRepoElement)
493 , ( ConflictResolutionPatchMSet NgramsTerm
494 , ConflictResolutionReplace ListType
498 type instance ConflictResolution NgramsPatch =
499 ConflictResolutionNgramsPatch
501 type PatchedNgramsPatch = Maybe NgramsRepoElement
502 type instance Patched NgramsPatch = PatchedNgramsPatch
504 instance Applicable (PairPatch (PatchMSet NgramsTerm) (Replace ListType)) NgramsRepoElement where
505 applicable (PairPatch (c, l)) n = applicable c (n ^. nre_children) <> applicable l (n ^. nre_list)
507 instance Action (PairPatch (PatchMSet NgramsTerm) (Replace ListType)) NgramsRepoElement where
508 act (PairPatch (c, l)) = (nre_children %~ act c)
509 . (nre_list %~ act l)
511 instance Applicable NgramsPatch (Maybe NgramsRepoElement) where
512 applicable p = applicable (p ^. _NgramsPatch)
514 instance Action NgramsPatch (Maybe NgramsRepoElement) where
515 act p = act (p ^. _NgramsPatch)
517 newtype NgramsTablePatch = NgramsTablePatch (PatchMap NgramsTerm NgramsPatch)
518 deriving (Eq, Show, Generic, ToJSON, FromJSON, Semigroup, Monoid, Validity, Transformable)
520 instance Serialise NgramsTablePatch
521 instance Serialise (PatchMap NgramsTerm NgramsPatch)
523 instance FromField NgramsTablePatch
525 fromField = fromField'
527 instance FromField (PatchMap TableNgrams.NgramsType (PatchMap NodeId NgramsTablePatch))
529 fromField = fromField'
531 type instance ConflictResolution NgramsTablePatch =
532 NgramsTerm -> ConflictResolutionNgramsPatch
535 type PatchedNgramsTablePatch = Map NgramsTerm PatchedNgramsPatch
536 -- ~ Patched (PatchMap NgramsTerm NgramsPatch)
537 type instance Patched NgramsTablePatch = PatchedNgramsTablePatch
539 makePrisms ''NgramsTablePatch
540 instance ToSchema (PatchMap NgramsTerm NgramsPatch)
541 instance ToSchema NgramsTablePatch
543 instance Applicable NgramsTablePatch (Maybe NgramsTableMap) where
544 applicable p = applicable (p ^. _NgramsTablePatch)
547 ngramsElementToRepo :: NgramsElement -> NgramsRepoElement
549 (NgramsElement { _ne_size = s
563 ngramsElementFromRepo :: NgramsTerm -> NgramsRepoElement -> NgramsElement
564 ngramsElementFromRepo
573 NgramsElement { _ne_size = s
578 , _ne_ngrams = ngrams
579 , _ne_occurrences = panic $ "API.Ngrams.Types._ne_occurrences"
581 -- Here we could use 0 if we want to avoid any `panic`.
582 -- It will not happen using getTableNgrams if
583 -- getOccByNgramsOnly provides a count of occurrences for
584 -- all the ngrams given.
588 reRootChildren :: NgramsTerm -> ReParent NgramsTerm
589 reRootChildren root ngram = do
590 nre <- use $ at ngram
591 forOf_ (_Just . nre_children . folded) nre $ \child -> do
592 at child . _Just . nre_root ?= root
593 reRootChildren root child
595 reParent :: Maybe RootParent -> ReParent NgramsTerm
596 reParent rp child = do
597 at child . _Just %= ( (nre_parent .~ (_rp_parent <$> rp))
598 . (nre_root .~ (_rp_root <$> rp))
600 reRootChildren (fromMaybe child (rp ^? _Just . rp_root)) child
602 reParentAddRem :: RootParent -> NgramsTerm -> ReParent AddRem
603 reParentAddRem rp child p =
604 reParent (if isRem p then Nothing else Just rp) child
606 reParentNgramsPatch :: NgramsTerm -> ReParent NgramsPatch
607 reParentNgramsPatch parent ngramsPatch = do
608 root_of_parent <- use (at parent . _Just . nre_root)
610 root = fromMaybe parent root_of_parent
611 rp = RootParent { _rp_root = root, _rp_parent = parent }
612 itraverse_ (reParentAddRem rp) (ngramsPatch ^. patch_children . _PatchMSet . _PatchMap)
613 -- TODO FoldableWithIndex/TraversableWithIndex for PatchMap
615 reParentNgramsTablePatch :: ReParent NgramsTablePatch
616 reParentNgramsTablePatch p = itraverse_ reParentNgramsPatch (p ^. _NgramsTablePatch. _PatchMap)
617 -- TODO FoldableWithIndex/TraversableWithIndex for PatchMap
619 ------------------------------------------------------------------------
621 instance Action NgramsTablePatch (Maybe NgramsTableMap) where
623 fmap (execState (reParentNgramsTablePatch p)) .
624 act (p ^. _NgramsTablePatch)
626 instance Arbitrary NgramsTablePatch where
627 arbitrary = NgramsTablePatch <$> PM.fromMap <$> arbitrary
629 -- Should it be less than an Lens' to preserve PatchMap's abstraction.
630 -- ntp_ngrams_patches :: Lens' NgramsTablePatch (Map NgramsTerm NgramsPatch)
631 -- ntp_ngrams_patches = _NgramsTablePatch . undefined
633 type ReParent a = forall m. MonadState NgramsTableMap m => a -> m ()
635 ------------------------------------------------------------------------
638 data Versioned a = Versioned
639 { _v_version :: Version
642 deriving (Generic, Show, Eq)
643 deriveJSON (unPrefix "_v_") ''Versioned
644 makeLenses ''Versioned
645 instance (Typeable a, ToSchema a) => ToSchema (Versioned a) where
646 declareNamedSchema = wellNamedSchema "_v_"
647 instance Arbitrary a => Arbitrary (Versioned a) where
648 arbitrary = Versioned 1 <$> arbitrary -- TODO 1 is constant so far
649 ------------------------------------------------------------------------
652 data VersionedWithCount a = VersionedWithCount
653 { _vc_version :: Version
657 deriving (Generic, Show, Eq)
658 deriveJSON (unPrefix "_vc_") ''VersionedWithCount
659 makeLenses ''VersionedWithCount
660 instance (Typeable a, ToSchema a) => ToSchema (VersionedWithCount a) where
661 declareNamedSchema = wellNamedSchema "_vc_"
662 instance Arbitrary a => Arbitrary (VersionedWithCount a) where
663 arbitrary = VersionedWithCount 1 1 <$> arbitrary -- TODO 1 is constant so far
665 toVersionedWithCount :: Count -> Versioned a -> VersionedWithCount a
666 toVersionedWithCount count (Versioned version data_) = VersionedWithCount version count data_
667 ------------------------------------------------------------------------
671 { _r_version :: !Version
674 -- first patch in the list is the most recent
676 deriving (Generic, Show)
678 ----------------------------------------------------------------------
680 instance (FromJSON s, FromJSON p) => FromJSON (Repo s p) where
681 parseJSON = genericParseJSON $ unPrefix "_r_"
683 instance (ToJSON s, ToJSON p) => ToJSON (Repo s p) where
684 toJSON = genericToJSON $ unPrefix "_r_"
685 toEncoding = genericToEncoding $ unPrefix "_r_"
687 instance (Serialise s, Serialise p) => Serialise (Repo s p)
691 initRepo :: Monoid s => Repo s p
692 initRepo = Repo 1 mempty []
698 type RepoCmdM env err m =
700 , HasConnectionPool env
705 ------------------------------------------------------------------------
709 instance Arbitrary NgramsRepoElement where
710 arbitrary = elements $ map ngramsElementToRepo ns
712 NgramsTable ns = mockTable
714 instance FromHttpApiData (Map TableNgrams.NgramsType (Versioned NgramsTableMap))
716 parseUrlPiece x = maybeToEither x (decode $ cs x)
718 ngramsTypeFromTabType :: TabType -> TableNgrams.NgramsType
719 ngramsTypeFromTabType tabType =
720 let here = "Garg.API.Ngrams: " :: Text in
722 Sources -> TableNgrams.Sources
723 Authors -> TableNgrams.Authors
724 Institutes -> TableNgrams.Institutes
725 Terms -> TableNgrams.NgramsTerms
726 _ -> panic $ here <> "No Ngrams for this tab"
727 -- TODO: This `panic` would disapear with custom NgramsType.
732 data UpdateTableNgramsCharts = UpdateTableNgramsCharts
733 { _utn_tab_type :: !TabType
734 , _utn_list_id :: !ListId
735 } deriving (Eq, Show, Generic)
737 makeLenses ''UpdateTableNgramsCharts
738 instance FromJSON UpdateTableNgramsCharts where
739 parseJSON = genericParseJSON $ jsonOptions "_utn_"
741 instance ToJSON UpdateTableNgramsCharts where
742 toJSON = genericToJSON $ jsonOptions "_utn_"
744 instance ToSchema UpdateTableNgramsCharts where
745 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_utn_")
747 ------------------------------------------------------------------------
748 type NgramsList = (Map TableNgrams.NgramsType (Versioned NgramsTableMap))