2 Module : Gargantext.API.Ngrams
3 Description : Server API
4 Copyright : (c) CNRS, 2017-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
13 get ngrams filtered by NgramsType
18 {-# LANGUAGE ConstraintKinds #-}
19 {-# LANGUAGE DataKinds #-}
20 {-# LANGUAGE DeriveGeneric #-}
21 {-# LANGUAGE NoImplicitPrelude #-}
22 {-# LANGUAGE OverloadedStrings #-}
23 {-# LANGUAGE ScopedTypeVariables #-}
24 {-# LANGUAGE TemplateHaskell #-}
25 {-# LANGUAGE TypeOperators #-}
26 {-# LANGUAGE FlexibleInstances #-}
27 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
28 {-# LANGUAGE MultiParamTypeClasses #-}
29 {-# LANGUAGE RankNTypes #-}
30 {-# LANGUAGE TypeFamilies #-}
31 {-# OPTIONS -fno-warn-orphans #-}
33 module Gargantext.API.Ngrams
36 import Prelude (Enum, Bounded, Semigroup(..), minBound, maxBound {-, round-})
37 -- import Gargantext.Database.Schema.User (UserId)
38 import Data.Functor (($>))
39 import Data.Patch.Class (Replace, replace, Action(act), Applicable(..),
40 Composable(..), Transformable(..),
41 PairPatch(..), Patched, ConflictResolution,
42 ConflictResolutionReplace)
43 import qualified Data.Map.Strict.Patch as PM
45 --import Data.Semigroup
47 -- import Data.Maybe (isJust)
48 -- import Data.Tuple.Extra (first)
49 import qualified Data.Map.Strict as Map
50 import Data.Map.Strict (Map)
51 --import qualified Data.Set as Set
52 import Control.Concurrent
53 import Control.Lens (makeLenses, makePrisms, Getter, Prism', prism', Iso', iso, from, (^..), (.~), (#), to, {-withIndex, folded, ifolded,-} view, (^.), (+~), (%~), at, _Just, Each(..), dropping, taking)
54 import Control.Monad (guard)
55 import Control.Monad.Error.Class (MonadError, throwError)
56 import Control.Monad.Reader
58 import Data.Aeson.TH (deriveJSON)
59 import Data.Either(Either(Left))
60 -- import Data.Map (lookup)
61 import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap
62 import Data.Swagger hiding (version, patch)
63 import Data.Text (Text)
65 import GHC.Generics (Generic)
66 import Gargantext.Core.Utils.Prefix (unPrefix)
67 import Gargantext.Database.Schema.Node (defaultList, HasNodeError)
68 -- import Gargantext.Database.Schema.Ngrams (NgramsTypeId, ngramsTypeId, NgramsTableData(..))
69 import Gargantext.Database.Schema.Ngrams (NgramsType)
70 import qualified Gargantext.Database.Schema.Ngrams as Ngrams
71 -- import Gargantext.Database.Schema.NodeNgram hiding (Action)
72 import Gargantext.Database.Utils (CmdM)
73 import Gargantext.Prelude
74 -- import Gargantext.Core.Types (ListTypeId, listTypeId)
75 import Gargantext.Core.Types (ListType(..), ListId, CorpusId, Limit, Offset)
76 import Servant hiding (Patch)
77 import Test.QuickCheck (elements)
78 import Test.QuickCheck.Arbitrary (Arbitrary, arbitrary)
80 ------------------------------------------------------------------------
81 --data FacetFormat = Table | Chart
82 data TabType = Docs | Terms | Sources | Authors | Institutes | Trash
84 deriving (Generic, Enum, Bounded)
86 instance FromHttpApiData TabType
88 parseUrlPiece "Docs" = pure Docs
89 parseUrlPiece "Terms" = pure Terms
90 parseUrlPiece "Sources" = pure Sources
91 parseUrlPiece "Institutes" = pure Institutes
92 parseUrlPiece "Authors" = pure Authors
93 parseUrlPiece "Trash" = pure Trash
95 parseUrlPiece "Contacts" = pure Contacts
97 parseUrlPiece _ = Left "Unexpected value of TabType"
99 instance ToParamSchema TabType
100 instance ToJSON TabType
101 instance FromJSON TabType
102 instance ToSchema TabType
103 instance Arbitrary TabType
105 arbitrary = elements [minBound .. maxBound]
107 newtype MSet a = MSet (Map a ())
108 deriving (Eq, Ord, Show, Generic, Arbitrary, Semigroup, Monoid)
110 instance ToJSON a => ToJSON (MSet a) where
111 toJSON (MSet m) = toJSON (Map.keys m)
112 toEncoding (MSet m) = toEncoding (Map.keys m)
114 mSetFromSet :: Set a -> MSet a
115 mSetFromSet = MSet . Map.fromSet (const ())
117 mSetFromList :: Ord a => [a] -> MSet a
118 mSetFromList = MSet . Map.fromList . map (\x -> (x, ()))
120 instance (Ord a, FromJSON a) => FromJSON (MSet a) where
121 parseJSON = fmap mSetFromList . parseJSON
123 instance (ToJSONKey a, ToSchema a) => ToSchema (MSet a) where
126 ------------------------------------------------------------------------
127 type NgramsTerm = Text
130 NgramsElement { _ne_ngrams :: NgramsTerm
131 , _ne_list :: ListType
132 , _ne_occurrences :: Int
133 , _ne_parent :: Maybe NgramsTerm
134 , _ne_children :: MSet NgramsTerm
136 deriving (Ord, Eq, Show, Generic)
138 deriveJSON (unPrefix "_ne_") ''NgramsElement
139 makeLenses ''NgramsElement
141 instance ToSchema NgramsElement
142 instance Arbitrary NgramsElement where
143 arbitrary = elements [NgramsElement "sport" GraphList 1 Nothing mempty]
145 ------------------------------------------------------------------------
146 newtype NgramsTable = NgramsTable [NgramsElement]
147 deriving (Ord, Eq, Generic, ToJSON, FromJSON, Show)
149 makePrisms ''NgramsTable
151 instance Each NgramsTable NgramsTable NgramsElement NgramsElement where
152 each = _NgramsTable . each
155 -- | TODO Check N and Weight
157 toNgramsElement :: [NgramsTableData] -> [NgramsElement]
158 toNgramsElement ns = map toNgramsElement' ns
160 toNgramsElement' (NgramsTableData _ p t _ lt w) = NgramsElement t lt' (round w) p' c'
164 Just x -> lookup x mapParent
165 c' = maybe mempty identity $ lookup t mapChildren
166 lt' = maybe (panic "API.Ngrams: listypeId") identity lt
168 mapParent :: Map Int Text
169 mapParent = Map.fromListWith (<>) $ map (\(NgramsTableData i _ t _ _ _) -> (i,t)) ns
171 mapChildren :: Map Text (Set Text)
172 mapChildren = Map.mapKeys (\i -> (maybe (panic "API.Ngrams.mapChildren: ParentId with no Terms: Impossible") identity $ lookup i mapParent))
173 $ Map.fromListWith (<>)
174 $ map (first fromJust)
175 $ filter (isJust . fst)
176 $ map (\(NgramsTableData _ p t _ _ _) -> (p, Set.singleton t)) ns
179 mockTable :: NgramsTable
180 mockTable = NgramsTable
181 [ NgramsElement "animal" GraphList 1 Nothing (mSetFromList ["dog", "cat"])
182 , NgramsElement "cat" GraphList 1 (Just "animal") mempty
183 , NgramsElement "cats" StopList 4 Nothing mempty
184 , NgramsElement "dog" GraphList 3 (Just "animal")(mSetFromList ["dogs"])
185 , NgramsElement "dogs" StopList 4 (Just "dog") mempty
186 , NgramsElement "fox" GraphList 1 Nothing mempty
187 , NgramsElement "object" CandidateList 2 Nothing mempty
188 , NgramsElement "nothing" StopList 4 Nothing mempty
189 , NgramsElement "organic" GraphList 3 Nothing (mSetFromList ["flower"])
190 , NgramsElement "flower" GraphList 3 (Just "organic") mempty
191 , NgramsElement "moon" CandidateList 1 Nothing mempty
192 , NgramsElement "sky" StopList 1 Nothing mempty
195 instance Arbitrary NgramsTable where
196 arbitrary = pure mockTable
198 instance ToSchema NgramsTable
200 ------------------------------------------------------------------------
201 type NgramsTableMap = Map NgramsTerm NgramsElement
203 ------------------------------------------------------------------------
204 -- On the Client side:
205 --data Action = InGroup NgramsId NgramsId
206 -- | OutGroup NgramsId NgramsId
207 -- | SetListType NgramsId ListType
209 data PatchSet a = PatchSet
213 deriving (Eq, Ord, Show, Generic)
215 makeLenses ''PatchSet
216 makePrisms ''PatchSet
218 instance ToJSON a => ToJSON (PatchSet a) where
219 toJSON = genericToJSON $ unPrefix "_"
220 toEncoding = genericToEncoding $ unPrefix "_"
222 instance (Ord a, FromJSON a) => FromJSON (PatchSet a) where
223 parseJSON = genericParseJSON $ unPrefix "_"
226 instance (Ord a, Arbitrary a) => Arbitrary (PatchSet a) where
227 arbitrary = PatchSet <$> arbitrary <*> arbitrary
229 type instance Patched (PatchSet a) = Set a
231 type ConflictResolutionPatchSet a = SimpleConflictResolution' (Set a)
232 type instance ConflictResolution (PatchSet a) = ConflictResolutionPatchSet a
234 instance Ord a => Semigroup (PatchSet a) where
235 p <> q = PatchSet { _rem = (q ^. rem) `Set.difference` (p ^. add) <> p ^. rem
236 , _add = (q ^. add) `Set.difference` (p ^. rem) <> p ^. add
239 instance Ord a => Monoid (PatchSet a) where
240 mempty = PatchSet mempty mempty
242 instance Ord a => Group (PatchSet a) where
243 invert (PatchSet r a) = PatchSet a r
245 instance Ord a => Composable (PatchSet a) where
246 composable _ _ = undefined
248 instance Ord a => Action (PatchSet a) (Set a) where
249 act p source = (source `Set.difference` (p ^. rem)) <> p ^. add
251 instance Applicable (PatchSet a) (Set a) where
252 applicable _ _ = mempty
254 instance Ord a => Validity (PatchSet a) where
255 validate p = check (Set.disjoint (p ^. rem) (p ^. add)) "_rem and _add should be dijoint"
257 instance Ord a => Transformable (PatchSet a) where
258 transformable = undefined
260 conflicts _p _q = undefined
262 transformWith conflict p q = undefined conflict p q
264 instance ToSchema a => ToSchema (PatchSet a)
267 type AddRem = Replace (Maybe ())
269 type PatchMap = PM.PatchMap
271 newtype PatchMSet a = PatchMSet (PatchMap a AddRem)
272 deriving (Eq, Show, Generic, Validity, Semigroup, Monoid, Transformable, Composable)
274 type ConflictResolutionPatchMSet a = a -> ConflictResolutionReplace (Maybe ())
275 type instance ConflictResolution (PatchMSet a) = ConflictResolutionPatchMSet a
277 -- TODO this breaks module abstraction
278 makePrisms ''PM.PatchMap
280 makePrisms ''PatchMSet
282 _PatchMSetIso :: Ord a => Iso' (PatchMSet a) (PatchSet a)
283 _PatchMSetIso = _PatchMSet . _PatchMap . iso f g . from _PatchSet
285 remPatch = replace (Just ()) Nothing
286 addPatch = replace Nothing (Just ())
287 isRem :: Replace (Maybe ()) -> Bool
288 isRem = (== remPatch)
289 f :: Ord a => Map a (Replace (Maybe ())) -> (Set a, Set a)
290 f m = (Map.keysSet rems, Map.keysSet adds)
292 (rems, adds) = Map.partition isRem m
293 g :: Ord a => (Set a, Set a) -> Map a (Replace (Maybe ()))
294 g (rems, adds) = Map.fromSet (const remPatch) rems
295 <> Map.fromSet (const addPatch) adds
297 instance Ord a => Action (PatchMSet a) (MSet a) where
298 act (PatchMSet p) (MSet m) = MSet $ act p m
300 instance Ord a => Applicable (PatchMSet a) (MSet a) where
301 applicable (PatchMSet p) (MSet m) = applicable p m
303 instance (Ord a, ToJSON a) => ToJSON (PatchMSet a) where
304 toJSON = toJSON . view _PatchMSetIso
305 toEncoding = toEncoding . view _PatchMSetIso
307 instance (Ord a, FromJSON a) => FromJSON (PatchMSet a) where
308 parseJSON = fmap (_PatchMSetIso #) . parseJSON
310 instance (Ord a, Arbitrary a) => Arbitrary (PatchMSet a) where
311 arbitrary = (PatchMSet . PM.fromMap) <$> arbitrary
313 instance ToSchema a => ToSchema (PatchMSet a) where
315 declareNamedSchema _ = undefined
317 type instance Patched (PatchMSet a) = MSet a
319 instance (Eq a, Arbitrary a) => Arbitrary (Replace a) where
320 arbitrary = uncurry replace <$> arbitrary
321 -- If they happen to be equal then the patch is Keep.
323 instance ToSchema a => ToSchema (Replace a) where
324 declareNamedSchema (_ :: proxy (Replace a)) = do
325 -- TODO Keep constructor is not supported here.
326 aSchema <- declareSchemaRef (Proxy :: Proxy a)
327 return $ NamedSchema (Just "Replace") $ mempty
328 & type_ .~ SwaggerObject
330 InsOrdHashMap.fromList
334 & required .~ [ "old", "new" ]
337 NgramsPatch { _patch_children :: PatchMSet NgramsTerm
338 , _patch_list :: Replace ListType -- TODO Map UserId ListType
340 deriving (Eq, Show, Generic)
342 deriveJSON (unPrefix "_") ''NgramsPatch
343 makeLenses ''NgramsPatch
345 instance ToSchema NgramsPatch
347 instance Arbitrary NgramsPatch where
348 arbitrary = NgramsPatch <$> arbitrary <*> (replace <$> arbitrary <*> arbitrary)
350 type NgramsPatchIso = PairPatch (PatchMSet NgramsTerm) (Replace ListType)
352 _NgramsPatch :: Iso' NgramsPatch NgramsPatchIso
353 _NgramsPatch = iso (\(NgramsPatch c l) -> c :*: l) (\(c :*: l) -> NgramsPatch c l)
355 instance Semigroup NgramsPatch where
356 p <> q = _NgramsPatch # (p ^. _NgramsPatch <> q ^. _NgramsPatch)
358 instance Monoid NgramsPatch where
359 mempty = _NgramsPatch # mempty
361 instance Validity NgramsPatch where
362 validate p = p ^. _NgramsPatch . to validate
364 instance Transformable NgramsPatch where
365 transformable p q = transformable (p ^. _NgramsPatch) (q ^. _NgramsPatch)
367 conflicts p q = conflicts (p ^. _NgramsPatch) (q ^. _NgramsPatch)
369 transformWith conflict p q = (_NgramsPatch # p', _NgramsPatch # q')
371 (p', q') = transformWith conflict (p ^. _NgramsPatch) (q ^. _NgramsPatch)
373 type ConflictResolutionNgramsPatch =
374 ( ConflictResolutionPatchMSet NgramsTerm
375 , ConflictResolutionReplace ListType
377 type instance ConflictResolution NgramsPatch =
378 ConflictResolutionNgramsPatch
380 type PatchedNgramsPatch = (Set NgramsTerm, ListType)
381 -- ~ Patched NgramsPatchIso
382 type instance Patched NgramsPatch = PatchedNgramsPatch
384 instance Applicable NgramsPatch (Maybe NgramsElement) where
385 applicable p Nothing = check (p == mempty) "NgramsPatch should be empty here"
386 applicable p (Just ne) =
387 -- TODO how to patch _ne_parent ?
388 applicable (p ^. patch_children) (ne ^. ne_children) <>
389 applicable (p ^. patch_list) (ne ^. ne_list)
391 instance Action NgramsPatch (Maybe NgramsElement) where
392 act _ Nothing = Nothing
394 -- TODO how to patch _ne_parent ?
395 ne & ne_children %~ act (p ^. patch_children)
396 & ne_list %~ act (p ^. patch_list)
399 newtype NgramsTablePatch = NgramsTablePatch (PatchMap NgramsTerm NgramsPatch)
400 deriving (Eq, Show, Generic, ToJSON, FromJSON, Semigroup, Monoid, Validity, Transformable)
402 --instance (Ord k, Action pv (Maybe v)) => Action (PatchMap k pv) (Map k v) where
404 type instance ConflictResolution NgramsTablePatch =
405 NgramsTerm -> ConflictResolutionNgramsPatch
407 type PatchedNgramsTablePatch = Map NgramsTerm PatchedNgramsPatch
408 -- ~ Patched (PatchMap NgramsTerm NgramsPatch)
409 type instance Patched NgramsTablePatch = PatchedNgramsTablePatch
411 makePrisms ''NgramsTablePatch
412 instance ToSchema (PatchMap NgramsTerm NgramsPatch)
413 instance ToSchema NgramsTablePatch
415 instance Applicable NgramsTablePatch (Maybe NgramsTableMap) where
416 applicable p = applicable (p ^. _NgramsTablePatch)
418 instance Action NgramsTablePatch (Maybe NgramsTableMap) where
419 act p = act (p ^. _NgramsTablePatch)
420 -- (v ^? _Just . _NgramsTable)
421 -- ^? _Just . from _NgramsTable
423 instance Arbitrary NgramsTablePatch where
424 arbitrary = NgramsTablePatch <$> PM.fromMap <$> arbitrary
426 -- Should it be less than an Lens' to preserve PatchMap's abstraction.
427 -- ntp_ngrams_patches :: Lens' NgramsTablePatch (Map NgramsTerm NgramsPatch)
428 -- ntp_ngrams_patches = _NgramsTablePatch . undefined
430 -- TODO: replace by mempty once we have the Monoid instance
431 emptyNgramsTablePatch :: NgramsTablePatch
432 emptyNgramsTablePatch = NgramsTablePatch mempty
434 ------------------------------------------------------------------------
435 ------------------------------------------------------------------------
438 data Versioned a = Versioned
439 { _v_version :: Version
443 deriveJSON (unPrefix "_v_") ''Versioned
444 makeLenses ''Versioned
445 instance ToSchema a => ToSchema (Versioned a)
446 instance Arbitrary a => Arbitrary (Versioned a) where
447 arbitrary = Versioned 1 <$> arbitrary -- TODO 1 is constant so far
450 -- TODO sequencs of modifications (Patchs)
451 type NgramsIdPatch = Patch NgramsId NgramsPatch
453 ngramsPatch :: Int -> NgramsPatch
454 ngramsPatch n = NgramsPatch (DM.fromList [(1, StopList)]) (Set.fromList [n]) Set.empty
456 toEdit :: NgramsId -> NgramsPatch -> Edit NgramsId NgramsPatch
457 toEdit n p = Edit n p
458 ngramsIdPatch :: Patch NgramsId NgramsPatch
459 ngramsIdPatch = fromList $ catMaybes $ reverse [ replace (1::NgramsId) (Just $ ngramsPatch 1) Nothing
460 , replace (1::NgramsId) Nothing (Just $ ngramsPatch 2)
461 , replace (2::NgramsId) Nothing (Just $ ngramsPatch 2)
464 -- applyPatchBack :: Patch -> IO Patch
465 -- isEmptyPatch = Map.all (\x -> Set.isEmpty (add_children x) && Set.isEmpty ... )
467 ------------------------------------------------------------------------
468 ------------------------------------------------------------------------
469 ------------------------------------------------------------------------
471 type TableNgramsApiGet = Summary " Table Ngrams API Get"
472 :> QueryParam "ngramsType" TabType
473 :> QueryParam "list" ListId
474 :> QueryParam "limit" Limit
475 :> QueryParam "offset" Offset
476 :> Get '[JSON] (Versioned NgramsTable)
478 type TableNgramsApi = Summary " Table Ngrams API Change"
479 :> QueryParam "ngramsType" TabType
480 :> QueryParam "list" ListId
481 :> ReqBody '[JSON] (Versioned NgramsTablePatch)
482 :> Put '[JSON] (Versioned NgramsTablePatch)
484 data NgramError = UnsupportedVersion
487 class HasNgramError e where
488 _NgramError :: Prism' e NgramError
490 instance HasNgramError ServantErr where
491 _NgramError = prism' make match
493 err = err500 { errBody = "NgramError: Unsupported version" }
494 make UnsupportedVersion = err
495 match e = guard (e == err) $> UnsupportedVersion
497 ngramError :: (MonadError e m, HasNgramError e) => NgramError -> m a
498 ngramError nne = throwError $ _NgramError # nne
501 -- TODO: Replace.old is ignored which means that if the current list
502 -- `GraphList` and that the patch is `Replace CandidateList StopList` then
503 -- the list is going to be `StopList` while it should keep `GraphList`.
504 -- However this should not happen in non conflicting situations.
505 mkListsUpdate :: NgramsType -> NgramsTablePatch -> [(NgramsTypeId, NgramsTerm, ListTypeId)]
506 mkListsUpdate nt patches =
507 [ (ngramsTypeId nt, ng, listTypeId lt)
508 | (ng, patch) <- patches ^.. ntp_ngrams_patches . ifolded . withIndex
509 , lt <- patch ^.. patch_list . new
512 mkChildrenGroups :: (PatchSet NgramsTerm -> Set NgramsTerm)
515 -> [(NgramsTypeId, NgramsParent, NgramsChild)]
516 mkChildrenGroups addOrRem nt patches =
517 [ (ngramsTypeId nt, parent, child)
518 | (parent, patch) <- patches ^.. ntp_ngrams_patches . ifolded . withIndex
519 , child <- patch ^.. patch_children . to addOrRem . folded
523 ngramsTypeFromTabType :: Maybe TabType -> NgramsType
524 ngramsTypeFromTabType maybeTabType =
525 let lieu = "Garg.API.Ngrams: " :: Text in
527 Nothing -> panic (lieu <> "Indicate the Table")
528 Just tab -> case tab of
529 Sources -> Ngrams.Sources
530 Authors -> Ngrams.Authors
531 Institutes -> Ngrams.Institutes
532 Terms -> Ngrams.NgramsTerms
533 _ -> panic $ lieu <> "No Ngrams for this tab"
535 ------------------------------------------------------------------------
537 { _r_version :: Version
540 -- ^ first patch in the list is the most recent
545 initRepo :: Monoid s => Repo s p
546 initRepo = Repo 1 mempty []
548 type NgramsState = Map ListId (Map NgramsType NgramsTableMap)
549 type NgramsStatePatch = PatchMap ListId (PatchMap NgramsType NgramsTablePatch)
550 type NgramsRepo = Repo NgramsState NgramsStatePatch
552 initMockRepo :: NgramsRepo
553 initMockRepo = Repo 1 s []
556 $ Map.singleton Ngrams.NgramsTerms
558 [ (n ^. ne_ngrams, n) | n <- mockTable ^. _NgramsTable ]
560 class HasRepoVar env where
561 repoVar :: Getter env (MVar NgramsRepo)
563 instance HasRepoVar (MVar NgramsRepo) where
566 type RepoCmdM env err m =
571 ------------------------------------------------------------------------
573 listTypeConflictResolution :: ListType -> ListType -> ListType
574 listTypeConflictResolution _ _ = undefined -- TODO Use Map User ListType
576 ngramsStatePatchConflictResolution
577 :: ListId -> NgramsType -> NgramsTerm
578 -> ConflictResolutionNgramsPatch
579 ngramsStatePatchConflictResolution _listId _ngramsType _ngramsTerm
580 = (undefined {- TODO think this through -}, listTypeConflictResolution)
582 class HasInvalidError e where
583 _InvalidError :: Prism' e Validation
585 instance HasInvalidError ServantErr where
586 _InvalidError = undefined {-prism' make match
588 err = err500 { errBody = "InvalidError" }
590 match e = guard (e == err) $> UnsupportedVersion-}
592 assertValid :: (MonadError e m, HasInvalidError e) => Validation -> m ()
593 assertValid v = when (not $ validationIsValid v) $ throwError $ _InvalidError # v
595 -- Apply the given patch to the DB and returns the patch to be applied on the
598 -- In this perliminary version the OT aspect is missing, therefore the version
599 -- number is always 1 and the returned patch is always empty.
600 tableNgramsPatch :: (HasNgramError err, HasNodeError err, HasInvalidError err,
602 => CorpusId -> Maybe TabType -> Maybe ListId
603 -> Versioned NgramsTablePatch
604 -> m (Versioned NgramsTablePatch)
605 tableNgramsPatch corpusId maybeTabType maybeList (Versioned p_version p_table) = do
606 let ngramsType = ngramsTypeFromTabType maybeTabType
607 listId <- maybe (defaultList corpusId) pure maybeList
608 let (p0, p0_validity) = PM.singleton ngramsType p_table
609 let (p, p_validity) = PM.singleton listId p0
611 assertValid p0_validity
612 assertValid p_validity
615 (p'_applicable, vq') <- liftIO $ modifyMVar var $ \r ->
617 q = mconcat $ take (r ^. r_version - p_version) (r ^. r_history)
618 (p', q') = transformWith ngramsStatePatchConflictResolution p q
619 r' = r & r_version +~ 1
621 & r_history %~ (p' :)
622 q'_table = q' ^. _PatchMap . at listId . _Just . _PatchMap . at ngramsType . _Just
623 p'_applicable = applicable p' (r ^. r_state)
625 pure (r', (p'_applicable, Versioned (r' ^. r_version) q'_table))
626 assertValid p'_applicable
630 when (version /= 1) $ ngramError UnsupportedVersion
631 updateNodeNgrams $ NodeNgramsUpdate
632 { _nnu_user_list_id = listId
633 , _nnu_lists_update = mkListsUpdate ngramsType patch
634 , _nnu_rem_children = mkChildrenGroups _rem ngramsType patch
635 , _nnu_add_children = mkChildrenGroups _add ngramsType patch
637 pure $ Versioned 1 emptyNgramsTablePatch
640 -- | TODO Errors management
641 -- TODO: polymorphic for Annuaire or Corpus or ...
642 getTableNgrams :: RepoCmdM env err m
643 => CorpusId -> Maybe TabType
644 -> Maybe ListId -> Maybe Limit -> Maybe Offset
645 -- -> Maybe MinSize -> Maybe MaxSize
647 -- -> Maybe Text -- full text search
648 -> m (Versioned NgramsTable)
649 getTableNgrams cId maybeTabType maybeListId mlimit moffset = do
650 let ngramsType = ngramsTypeFromTabType maybeTabType
651 listId <- maybe (defaultList cId) pure maybeListId
654 defaultLimit = 10 -- TODO
655 limit_ = maybe defaultLimit identity mlimit
656 offset_ = maybe 0 identity moffset
659 repo <- liftIO $ readMVar v
661 let ngrams = repo ^.. r_state
663 . at ngramsType . _Just
664 . taking limit_ (dropping offset_ each)
666 pure $ Versioned (repo ^. r_version) (NgramsTable ngrams)
670 Ngrams.getNgramsTableDb NodeDocument ngramsType (Ngrams.NgramsTableParam listId cId) limit_ offset_
672 -- printDebug "ngramsTableDatas" ngramsTableDatas
674 pure $ Versioned 1 $ NgramsTable (toNgramsElement ngramsTableDatas)