2 Module : Gargantext.Database.Types.Nodes
3 Description : Main Types of Nodes in Database
4 Copyright : (c) CNRS, 2017-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
12 {-# OPTIONS_GHC -fno-warn-orphans #-}
14 {-# LANGUAGE BangPatterns #-}
15 {-# LANGUAGE DeriveGeneric #-}
16 {-# LANGUAGE FlexibleInstances #-}
17 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
18 {-# LANGUAGE NoImplicitPrelude #-}
19 {-# LANGUAGE OverloadedStrings #-}
20 {-# LANGUAGE TemplateHaskell #-}
21 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
23 -- {-# LANGUAGE DuplicateRecordFields #-}
25 module Gargantext.Database.Types.Node
28 import Prelude (Enum, Bounded, minBound, maxBound)
30 import GHC.Generics (Generic)
32 import Control.Lens hiding (elements, (&))
33 import Control.Applicative ((<*>))
34 import Control.Monad (mzero)
37 import Data.Aeson.Types (emptyObject)
38 import Data.Aeson (Object, toJSON)
39 import Data.Aeson.TH (deriveJSON)
40 import Data.ByteString.Lazy (ByteString)
43 import Data.Monoid (mempty)
44 import Data.Text (Text, unpack)
45 import Data.Time (UTCTime)
48 import Text.Read (read)
49 import Text.Show (Show())
51 import Database.PostgreSQL.Simple.ToField (ToField, toField, toJSONField)
52 import Database.PostgreSQL.Simple.FromField (FromField, fromField)
55 import Test.QuickCheck.Arbitrary
56 import Test.QuickCheck (elements)
57 import Test.QuickCheck.Instances.Time ()
58 import Test.QuickCheck.Instances.Text ()
60 import Gargantext.Prelude
61 import Gargantext.Core.Utils.Prefix (unPrefix, unPrefixSwagger)
62 import Gargantext.Viz.Phylo (Phylo)
63 --import Gargantext.Database.Utils
64 ------------------------------------------------------------------------
65 newtype NodeId = NodeId Int
66 deriving (Show, Read, Generic, Num, Eq, Ord, Enum, ToJSONKey, FromJSONKey, ToJSON, FromJSON)
68 instance ToField NodeId where
69 toField (NodeId n) = toField n
72 instance FromField NodeId where
73 fromField field mdata = do
74 n <- fromField field mdata
76 then return $ NodeId n
79 instance ToSchema NodeId
85 ------------------------------------------------------------------------
86 data NodePoly id typename userId
88 hyperdata = Node { _node_id :: id
89 , _node_typename :: typename
91 , _node_userId :: userId
92 , _node_parentId :: parentId
97 , _node_hyperdata :: hyperdata
98 } deriving (Show, Generic)
99 $(deriveJSON (unPrefix "_node_") ''NodePoly)
100 $(makeLenses ''NodePoly)
102 -- | NodePoly indicates that Node has a Polymorphism Type
103 type Node json = NodePoly NodeId NodeTypeId UserId (Maybe ParentId) NodeName UTCTime json
107 ------------------------------------------------------------------------
110 instance FromHttpApiData NodeId where
111 parseUrlPiece n = pure $ NodeId $ (read . cs) n
113 instance ToParamSchema NodeId
114 instance Arbitrary NodeId where
115 arbitrary = NodeId <$> arbitrary
117 type ParentId = NodeId
118 type CorpusId = NodeId
120 type DocumentId = NodeId
123 type MasterCorpusId = CorpusId
124 type UserCorpusId = CorpusId
126 type GraphId = NodeId
127 type PhyloId = NodeId
128 type AnnuaireId = NodeId
129 type ContactId = NodeId
132 type MasterUserId = UserId
134 id2int :: NodeId -> Int
135 id2int (NodeId n) = n
137 ------------------------------------------------------------------------
138 data Status = Status { status_failed :: !Int
139 , status_succeeded :: !Int
140 , status_remaining :: !Int
141 } deriving (Show, Generic)
142 $(deriveJSON (unPrefix "status_") ''Status)
144 instance Arbitrary Status where
145 arbitrary = Status <$> arbitrary <*> arbitrary <*> arbitrary
147 ------------------------------------------------------------------------
148 data StatusV3 = StatusV3 { statusV3_error :: !(Maybe Text)
149 , statusV3_action :: !(Maybe Text)
150 } deriving (Show, Generic)
151 $(deriveJSON (unPrefix "statusV3_") ''StatusV3)
152 ------------------------------------------------------------------------
154 -- Only Hyperdata types should be member of this type class.
156 ------------------------------------------------------------------------
157 data HyperdataDocumentV3 = HyperdataDocumentV3 { hyperdataDocumentV3_publication_day :: !(Maybe Int)
158 , hyperdataDocumentV3_language_iso2 :: !(Maybe Text)
159 , hyperdataDocumentV3_publication_second :: !(Maybe Int)
160 , hyperdataDocumentV3_publication_minute :: !(Maybe Int)
161 , hyperdataDocumentV3_publication_month :: !(Maybe Int)
162 , hyperdataDocumentV3_publication_hour :: !(Maybe Int)
163 , hyperdataDocumentV3_error :: !(Maybe Text)
164 , hyperdataDocumentV3_language_iso3 :: !(Maybe Text)
165 , hyperdataDocumentV3_authors :: !(Maybe Text)
166 , hyperdataDocumentV3_publication_year :: !(Maybe Int)
167 , hyperdataDocumentV3_publication_date :: !(Maybe Text)
168 , hyperdataDocumentV3_language_name :: !(Maybe Text)
169 , hyperdataDocumentV3_statuses :: !(Maybe [StatusV3])
170 , hyperdataDocumentV3_realdate_full_ :: !(Maybe Text)
171 , hyperdataDocumentV3_source :: !(Maybe Text)
172 , hyperdataDocumentV3_abstract :: !(Maybe Text)
173 , hyperdataDocumentV3_title :: !(Maybe Text)
174 } deriving (Show, Generic)
175 $(deriveJSON (unPrefix "hyperdataDocumentV3_") ''HyperdataDocumentV3)
178 instance Hyperdata HyperdataDocumentV3
180 ------------------------------------------------------------------------
181 data HyperdataDocument = HyperdataDocument { _hyperdataDocument_bdd :: !(Maybe Text)
182 , _hyperdataDocument_doi :: !(Maybe Text)
183 , _hyperdataDocument_url :: !(Maybe Text)
184 , _hyperdataDocument_uniqId :: !(Maybe Text)
185 , _hyperdataDocument_uniqIdBdd :: !(Maybe Text)
186 , _hyperdataDocument_page :: !(Maybe Int)
187 , _hyperdataDocument_title :: !(Maybe Text)
188 , _hyperdataDocument_authors :: !(Maybe Text)
189 , _hyperdataDocument_institutes :: !(Maybe Text)
190 , _hyperdataDocument_source :: !(Maybe Text)
191 , _hyperdataDocument_abstract :: !(Maybe Text)
192 , _hyperdataDocument_publication_date :: !(Maybe Text)
193 , _hyperdataDocument_publication_year :: !(Maybe Int)
194 , _hyperdataDocument_publication_month :: !(Maybe Int)
195 , _hyperdataDocument_publication_day :: !(Maybe Int)
196 , _hyperdataDocument_publication_hour :: !(Maybe Int)
197 , _hyperdataDocument_publication_minute :: !(Maybe Int)
198 , _hyperdataDocument_publication_second :: !(Maybe Int)
199 , _hyperdataDocument_language_iso2 :: !(Maybe Text)
200 } deriving (Show, Generic)
202 $(deriveJSON (unPrefix "_hyperdataDocument_") ''HyperdataDocument)
203 $(makeLenses ''HyperdataDocument)
205 class ToHyperdataDocument a where
206 toHyperdataDocument :: a -> HyperdataDocument
208 instance ToHyperdataDocument HyperdataDocument
210 toHyperdataDocument = identity
212 instance Eq HyperdataDocument where
213 (==) h1 h2 = (==) (_hyperdataDocument_uniqId h1) (_hyperdataDocument_uniqId h2)
215 instance Ord HyperdataDocument where
216 compare h1 h2 = compare (_hyperdataDocument_publication_date h1) (_hyperdataDocument_publication_date h2)
218 instance Hyperdata HyperdataDocument
220 instance ToField HyperdataDocument where
221 toField = toJSONField
223 instance Arbitrary HyperdataDocument where
224 arbitrary = elements arbitraryHyperdataDocuments
226 arbitraryHyperdataDocuments :: [HyperdataDocument]
227 arbitraryHyperdataDocuments =
228 map toHyperdataDocument' ([ ("AI is big but less than crypto", "Troll System journal")
229 , ("Crypto is big but less than AI", "System Troll review" )
230 , ("Science is magic" , "Closed Source review")
231 , ("Open science for all" , "No Time" )
232 , ("Closed science for me" , "No Space" )
235 toHyperdataDocument' (t1,t2) =
236 HyperdataDocument Nothing Nothing Nothing Nothing Nothing Nothing (Just t1)
237 Nothing Nothing (Just t2) Nothing Nothing Nothing Nothing Nothing
238 Nothing Nothing Nothing Nothing
240 ------------------------------------------------------------------------
241 data LanguageNodes = LanguageNodes { languageNodes___unknown__ :: [Int]}
242 deriving (Show, Generic)
243 $(deriveJSON (unPrefix "languageNodes_") ''LanguageNodes)
245 ------------------------------------------------------------------------
246 -- level: debug | dev (fatal = critical)
247 data EventLevel = CRITICAL | FATAL | ERROR | WARNING | INFO | DEBUG
248 deriving (Show, Generic, Enum, Bounded)
250 instance FromJSON EventLevel
251 instance ToJSON EventLevel
253 instance Arbitrary EventLevel where
254 arbitrary = elements [minBound..maxBound]
256 instance ToSchema EventLevel where
257 declareNamedSchema proxy = genericDeclareNamedSchema defaultSchemaOptions proxy
259 ------------------------------------------------------------------------
261 data Event = Event { event_level :: !EventLevel
262 , event_message :: !Text
263 , event_date :: !UTCTime
264 } deriving (Show, Generic)
265 $(deriveJSON (unPrefix "event_") ''Event)
267 instance Arbitrary Event where
268 arbitrary = Event <$> arbitrary <*> arbitrary <*> arbitrary
270 instance ToSchema Event where
271 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "event_")
273 ------------------------------------------------------------------------
275 data Resource = Resource { resource_path :: !(Maybe Text)
276 , resource_scraper :: !(Maybe Text)
277 , resource_query :: !(Maybe Text)
278 , resource_events :: !([Event])
279 , resource_status :: !Status
280 , resource_date :: !UTCTime
281 } deriving (Show, Generic)
282 $(deriveJSON (unPrefix "resource_") ''Resource)
284 instance Arbitrary Resource where
285 arbitrary = Resource <$> arbitrary
292 instance ToSchema Resource where
293 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "resource_")
295 ------------------------------------------------------------------------
296 data HyperdataUser = HyperdataUser { hyperdataUser_language :: Maybe Text
297 } deriving (Show, Generic)
298 $(deriveJSON (unPrefix "hyperdataUser_") ''HyperdataUser)
300 instance Hyperdata HyperdataUser
301 ------------------------------------------------------------------------
302 data HyperdataFolder = HyperdataFolder { hyperdataFolder_desc :: Maybe Text
303 } deriving (Show, Generic)
304 $(deriveJSON (unPrefix "hyperdataFolder_") ''HyperdataFolder)
306 instance Hyperdata HyperdataFolder
307 ------------------------------------------------------------------------
308 data HyperdataCorpus = HyperdataCorpus { hyperdataCorpus_title :: !(Maybe Text)
309 , hyperdataCorpus_desc :: !(Maybe Text)
310 , hyperdataCorpus_query :: !(Maybe Text)
311 , hyperdataCorpus_authors :: !(Maybe Text)
312 , hyperdataCorpus_resources :: !(Maybe [Resource])
313 } deriving (Show, Generic)
314 $(deriveJSON (unPrefix "hyperdataCorpus_") ''HyperdataCorpus)
316 instance Hyperdata HyperdataCorpus
318 corpusExample :: ByteString
319 corpusExample = "" -- TODO
321 defaultCorpus :: HyperdataCorpus
322 defaultCorpus = (HyperdataCorpus (Just "Title") (Just "Descr") (Just "Bool query") (Just "Authors") Nothing)
324 hyperdataCorpus :: HyperdataCorpus
325 hyperdataCorpus = case decode corpusExample of
327 Nothing -> defaultCorpus
329 instance Arbitrary HyperdataCorpus where
330 arbitrary = pure hyperdataCorpus -- TODO
332 ------------------------------------------------------------------------
334 data HyperdataList = HyperdataList {hd_list :: !(Maybe Text)
335 } deriving (Show, Generic)
336 $(deriveJSON (unPrefix "hd_") ''HyperdataList)
338 instance Hyperdata HyperdataList
340 ------------------------------------------------------------------------
341 data HyperdataAnnuaire = HyperdataAnnuaire { hyperdataAnnuaire_title :: !(Maybe Text)
342 , hyperdataAnnuaire_desc :: !(Maybe Text)
343 } deriving (Show, Generic)
344 $(deriveJSON (unPrefix "hyperdataAnnuaire_") ''HyperdataAnnuaire)
346 instance Hyperdata HyperdataAnnuaire
348 hyperdataAnnuaire :: HyperdataAnnuaire
349 hyperdataAnnuaire = HyperdataAnnuaire (Just "Annuaire Title") (Just "Annuaire Description")
351 instance Arbitrary HyperdataAnnuaire where
352 arbitrary = pure hyperdataAnnuaire -- TODO
354 ------------------------------------------------------------------------
355 newtype HyperdataAny = HyperdataAny Object
356 deriving (Show, Generic, ToJSON, FromJSON)
358 instance Hyperdata HyperdataAny
360 instance Arbitrary HyperdataAny where
361 arbitrary = pure $ HyperdataAny mempty -- TODO produce arbitrary objects
362 ------------------------------------------------------------------------
365 instance Arbitrary HyperdataList' where
366 arbitrary = elements [HyperdataList' (Just "from list A")]
370 data HyperdataListModel = HyperdataListModel { _hlm_params :: !(Int, Int)
372 , _hlm_score :: !(Maybe Double)
373 } deriving (Show, Generic)
375 instance Hyperdata HyperdataListModel
376 instance Arbitrary HyperdataListModel where
377 arbitrary = elements [HyperdataListModel (100,100) "models/example.model" Nothing]
379 $(deriveJSON (unPrefix "_hlm_") ''HyperdataListModel)
380 $(makeLenses ''HyperdataListModel)
382 ------------------------------------------------------------------------
383 data HyperdataScore = HyperdataScore { hyperdataScore_preferences :: !(Maybe Text)
384 } deriving (Show, Generic)
385 $(deriveJSON (unPrefix "hyperdataScore_") ''HyperdataScore)
387 instance Hyperdata HyperdataScore
389 ------------------------------------------------------------------------
391 data HyperdataResource = HyperdataResource { hyperdataResource_preferences :: !(Maybe Text)
392 } deriving (Show, Generic)
393 $(deriveJSON (unPrefix "hyperdataResource_") ''HyperdataResource)
395 instance Hyperdata HyperdataResource
397 ------------------------------------------------------------------------
398 data HyperdataDashboard = HyperdataDashboard { hyperdataDashboard_preferences :: !(Maybe Text)
399 } deriving (Show, Generic)
400 $(deriveJSON (unPrefix "hyperdataDashboard_") ''HyperdataDashboard)
402 instance Hyperdata HyperdataDashboard
404 -- TODO add the Graph Structure here
405 data HyperdataGraph = HyperdataGraph { hyperdataGraph_preferences :: !(Maybe Text)
406 } deriving (Show, Generic)
407 $(deriveJSON (unPrefix "hyperdataGraph_") ''HyperdataGraph)
409 instance Hyperdata HyperdataGraph
411 ------------------------------------------------------------------------
413 -- TODO add the Graph Structure here
414 data HyperdataPhylo = HyperdataPhylo { hyperdataPhylo_preferences :: !(Maybe Text)
415 , hyperdataPhylo_data :: !(Maybe Phylo)
416 } deriving (Show, Generic)
417 $(deriveJSON (unPrefix "hyperdataPhylo_") ''HyperdataPhylo)
419 instance Hyperdata HyperdataPhylo
421 ------------------------------------------------------------------------
422 -- | TODO FEATURE: Notebook saved in the node
423 data HyperdataNotebook = HyperdataNotebook { hyperdataNotebook_preferences :: !(Maybe Text)
424 } deriving (Show, Generic)
425 $(deriveJSON (unPrefix "hyperdataNotebook_") ''HyperdataNotebook)
427 instance Hyperdata HyperdataNotebook
431 data HyperData = HyperdataTexts { hd_preferences :: Maybe Text }
432 | HyperdataList' { hd_preferences :: Maybe Text}
433 deriving (Show, Generic)
435 $(deriveJSON (unPrefix "hd_") ''HyperData)
437 instance Hyperdata HyperData
440 ------------------------------------------------------------------------
441 -- | Then a Node can be either a Folder or a Corpus or a Document
442 data NodeType = NodeUser
444 | NodeCorpus | NodeCorpusV3 | NodeTexts | NodeDocument
445 | NodeAnnuaire | NodeContact
446 | NodeGraph | NodePhylo
447 | NodeDashboard | NodeChart | NodeNoteBook
448 | NodeList | NodeListModel
449 deriving (Show, Read, Eq, Generic, Bounded, Enum)
458 allNodeTypes :: [NodeType]
459 allNodeTypes = [minBound ..]
461 instance FromJSON NodeType
462 instance ToJSON NodeType
464 instance FromHttpApiData NodeType
466 parseUrlPiece = Right . read . unpack
468 instance ToParamSchema NodeType
469 instance ToSchema NodeType
472 data NodePolySearch id typename userId
474 hyperdata search = NodeSearch { _ns_id :: id
475 , _ns_typename :: typename
476 , _ns_userId :: userId
477 -- , nodeUniqId :: hashId
478 , _ns_parentId :: parentId
482 , _ns_hyperdata :: hyperdata
483 , _ns_search :: search
484 } deriving (Show, Generic)
485 $(deriveJSON (unPrefix "_ns_") ''NodePolySearch)
486 $(makeLenses ''NodePolySearch)
488 type NodeSearch json = NodePolySearch NodeId NodeTypeId UserId (Maybe ParentId) NodeName UTCTime json (Maybe TSVector)
489 ------------------------------------------------------------------------
492 instance (Arbitrary hyperdata
494 ,Arbitrary nodeTypeId
496 ,Arbitrary nodeParentId
497 ) => Arbitrary (NodePoly nodeId nodeTypeId userId nodeParentId
498 NodeName UTCTime hyperdata) where
499 --arbitrary = Node 1 1 (Just 1) 1 "name" (jour 2018 01 01) (arbitrary) (Just "")
500 arbitrary = Node <$> arbitrary <*> arbitrary <*> arbitrary
501 <*> arbitrary <*> arbitrary <*> arbitrary
504 instance (Arbitrary hyperdata
506 ,Arbitrary nodeTypeId
508 ,Arbitrary nodeParentId
509 ) => Arbitrary (NodePolySearch nodeId nodeTypeId userId nodeParentId
510 NodeName UTCTime hyperdata (Maybe TSVector)) where
511 --arbitrary = Node 1 1 (Just 1) 1 "name" (jour 2018 01 01) (arbitrary) (Just "")
512 arbitrary = NodeSearch <$> arbitrary <*> arbitrary <*> arbitrary
513 <*> arbitrary <*> arbitrary <*> arbitrary
514 <*> arbitrary <*> arbitrary
517 ------------------------------------------------------------------------
518 hyperdataDocument :: HyperdataDocument
519 hyperdataDocument = case decode docExample of
521 Nothing -> HyperdataDocument Nothing Nothing Nothing Nothing
522 Nothing Nothing Nothing Nothing
523 Nothing Nothing Nothing Nothing
524 Nothing Nothing Nothing Nothing
525 Nothing Nothing Nothing
526 docExample :: ByteString
527 docExample = "{\"doi\":\"sdfds\",\"publication_day\":6,\"language_iso2\":\"en\",\"publication_minute\":0,\"publication_month\":7,\"language_iso3\":\"eng\",\"publication_second\":0,\"authors\":\"Nils Hovdenak, Kjell Haram\",\"publication_year\":2012,\"publication_date\":\"2012-07-06 00:00:00+00:00\",\"language_name\":\"English\",\"realdate_full_\":\"2012 01 12\",\"source\":\"European journal of obstetrics, gynecology, and reproductive biology\",\"abstract\":\"The literature was searched for publications on minerals and vitamins during pregnancy and the possible influence of supplements on pregnancy outcome.\",\"title\":\"Influence of mineral and vitamin supplements on pregnancy outcome.\",\"publication_hour\":0}"
529 instance ToSchema HyperdataCorpus where
530 declareNamedSchema proxy =
531 genericDeclareNamedSchema (unPrefixSwagger "hyperdataCorpus_") proxy
532 & mapped.schema.description ?~ "a corpus"
533 & mapped.schema.example ?~ toJSON hyperdataCorpus
535 instance ToSchema HyperdataAnnuaire where
536 declareNamedSchema proxy =
537 genericDeclareNamedSchema (unPrefixSwagger "hyperdataAnnuaire_") proxy
538 & mapped.schema.description ?~ "an annuaire"
539 & mapped.schema.example ?~ toJSON hyperdataAnnuaire
541 instance ToSchema HyperdataDocument where
542 declareNamedSchema proxy =
543 genericDeclareNamedSchema (unPrefixSwagger "_hyperdataDocument_") proxy
544 & mapped.schema.description ?~ "a document"
545 & mapped.schema.example ?~ toJSON hyperdataDocument
547 instance ToSchema HyperdataAny where
548 declareNamedSchema proxy =
549 pure $ genericNameSchema defaultSchemaOptions proxy mempty
550 & schema.description ?~ "a node"
551 & schema.example ?~ emptyObject -- TODO
554 instance ToSchema hyperdata =>
555 ToSchema (NodePoly NodeId NodeTypeId
560 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_node_")
562 instance ToSchema hyperdata =>
563 ToSchema (NodePoly NodeId NodeTypeId
565 (Maybe ParentId) NodeName
568 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_node_")
571 instance ToSchema hyperdata =>
572 ToSchema (NodePolySearch NodeId NodeTypeId
575 UTCTime hyperdata (Maybe TSVector)
577 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_ns_")
579 instance ToSchema hyperdata =>
580 ToSchema (NodePolySearch NodeId NodeTypeId
582 (Maybe ParentId) NodeName
583 UTCTime hyperdata (Maybe TSVector)
585 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_ns_")
588 instance ToSchema Status where
589 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "status_")