{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE ScopedTypeVariables        #-}
{-# LANGUAGE TypeFamilies               #-}

{- |
Module      :  Persistence.Diagnosis.hs
Copyright   :  (c) Uni Magdeburg 2017
License     :  GPLv2 or higher, see LICENSE.txt

Maintainer  :  Eugen Kuksa <kuksa@iks.cs.ovgu.de>
Stability   :  provisional
Portability :  portable
-}

module Persistence.FileVersion ( getFileVersion
                               , setFileVersionState
                               , setFileVersionStateOn
                               ) where

import Persistence.Database
import Persistence.DBConfig
import Persistence.Schema as SchemaClass
import Persistence.Schema.EvaluationStateType

import Control.Monad.IO.Class (MonadIO (..))
import qualified Control.Monad.Fail as Fail
import Database.Persist
import Database.Persist.Sql (toSqlKey)

setFileVersionStateOn :: (MonadIO m, Fail.MonadFail m)
                      => FileVersionId -> EvaluationStateType -> DBMonad m ()
setFileVersionStateOn :: FileVersionId -> EvaluationStateType -> DBMonad m ()
setFileVersionStateOn fileVersionKey :: FileVersionId
fileVersionKey state :: EvaluationStateType
state = do
  Just fileVersionValue :: FileVersion
fileVersionValue <- FileVersionId -> ReaderT SqlBackend m (Maybe FileVersion)
forall backend (m :: * -> *) record.
(PersistStoreRead backend, MonadIO m,
 PersistRecordBackend record backend) =>
Key record -> ReaderT backend m (Maybe record)
get FileVersionId
fileVersionKey
  Key Action -> [Update Action] -> DBMonad m ()
forall backend (m :: * -> *) record.
(PersistStoreWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
Key record -> [Update record] -> ReaderT backend m ()
update (FileVersion -> Key Action
fileVersionActionId FileVersion
fileVersionValue) [EntityField Action EvaluationStateType
forall typ. (typ ~ EvaluationStateType) => EntityField Action typ
ActionEvaluationState EntityField Action EvaluationStateType
-> EvaluationStateType -> Update Action
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Update v
=. EvaluationStateType
state]
  () -> DBMonad m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

setFileVersionState :: (MonadIO m, Fail.MonadFail m)
                    => DBContext -> EvaluationStateType -> DBMonad m ()
setFileVersionState :: DBContext -> EvaluationStateType -> DBMonad m ()
setFileVersionState dbContext :: DBContext
dbContext state :: EvaluationStateType
state = do
  (Entity fileVersionKey :: FileVersionId
fileVersionKey _) <- DBContext -> DBMonad m (Entity FileVersion)
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
DBContext -> DBMonad m (Entity FileVersion)
getFileVersion DBContext
dbContext
  FileVersionId -> EvaluationStateType -> DBMonad m ()
forall (m :: * -> *).
(MonadIO m, MonadFail m) =>
FileVersionId -> EvaluationStateType -> DBMonad m ()
setFileVersionStateOn FileVersionId
fileVersionKey EvaluationStateType
state

getFileVersion :: (MonadIO m, Fail.MonadFail m) => DBContext -> DBMonad m (Entity FileVersion)
getFileVersion :: DBContext -> DBMonad m (Entity FileVersion)
getFileVersion dbContext :: DBContext
dbContext =
  let fileVersionS :: String
fileVersionS = DBContext -> String
contextFileVersion DBContext
dbContext in
  if String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
fileVersionS
  then  DBContext -> DBMonad m (Entity FileVersion)
forall (m :: * -> *).
MonadIO m =>
DBContext -> DBMonad m (Entity FileVersion)
findOrCreateFileVersion DBContext
dbContext -- Hets has not been called by Ontohub
  else do -- Hets has been called by Ontohub
        Maybe (Entity FileVersion)
fileVersionM <-
          [Filter FileVersion]
-> [SelectOpt FileVersion]
-> ReaderT SqlBackend m (Maybe (Entity FileVersion))
forall backend (m :: * -> *) record.
(PersistQueryRead backend, MonadIO m,
 PersistRecordBackend record backend) =>
[Filter record]
-> [SelectOpt record] -> ReaderT backend m (Maybe (Entity record))
selectFirst [ EntityField FileVersion FileVersionId
forall typ. (typ ~ FileVersionId) => EntityField FileVersion typ
FileVersionId EntityField FileVersion FileVersionId
-> FileVersionId -> Filter FileVersion
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
==. Int64 -> FileVersionId
forall record.
ToBackendKey SqlBackend record =>
Int64 -> Key record
toSqlKey
                            (Integer -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (String -> Integer
forall a. Read a => String -> a
read String
fileVersionS :: Integer))] []
        case Maybe (Entity FileVersion)
fileVersionM of
          Nothing -> String -> DBMonad m (Entity FileVersion)
forall (m :: * -> *) a. MonadFail m => String -> m a
Fail.fail ("Could not find the FileVersion \"" String -> String -> String
forall a. [a] -> [a] -> [a]
++
                           String
fileVersionS String -> String -> String
forall a. [a] -> [a] -> [a]
++ "\"")
          Just fileVersion' :: Entity FileVersion
fileVersion' -> Entity FileVersion -> DBMonad m (Entity FileVersion)
forall (m :: * -> *) a. Monad m => a -> m a
return Entity FileVersion
fileVersion'

nonGitFileVersion :: String
nonGitFileVersion :: String
nonGitFileVersion = "non-git FileVersion"

findOrCreateFileVersion :: forall m . MonadIO m
                        => DBContext -> DBMonad m (Entity FileVersion)
findOrCreateFileVersion :: DBContext -> DBMonad m (Entity FileVersion)
findOrCreateFileVersion dbContext :: DBContext
dbContext = do
  let path :: String
path = DBContext -> String
contextFilePath DBContext
dbContext
  Maybe (Entity FileVersion)
fileVersionM <- String -> DBMonad m (Maybe (Entity FileVersion))
forall (m :: * -> *).
MonadIO m =>
String -> DBMonad m (Maybe (Entity FileVersion))
lastFileVersion String
path
  case Maybe (Entity FileVersion)
fileVersionM of
    Just fileVersion :: Entity FileVersion
fileVersion -> Entity FileVersion -> DBMonad m (Entity FileVersion)
forall (m :: * -> *) a. Monad m => a -> m a
return Entity FileVersion
fileVersion
    Nothing -> String -> DBMonad m (Entity FileVersion)
MonadIO m => String -> DBMonad m (Entity FileVersion)
create String
path
  where
    create :: MonadIO m => FilePath -> DBMonad m (Entity FileVersion)
    create :: String -> DBMonad m (Entity FileVersion)
create path :: String
path = do
        Entity repositoryKey :: Key Repository
repositoryKey _ <- DBMonad m (Entity Repository)
forall (m :: * -> *). MonadIO m => DBMonad m (Entity Repository)
repositoryFirstOrCreate
        Key Action
actionKey <- Action -> ReaderT SqlBackend m (Key Action)
forall backend (m :: * -> *) record.
(PersistStoreWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
record -> ReaderT backend m (Key record)
insert $WAction :: EvaluationStateType -> Maybe Text -> Action
Action
          { actionEvaluationState :: EvaluationStateType
actionEvaluationState = EvaluationStateType
NotYetEnqueued
          , actionMessage :: Maybe Text
actionMessage = Maybe Text
forall a. Maybe a
Nothing
          }
        let fileVersionValue :: FileVersion
fileVersionValue = $WFileVersion :: Key Action -> Key Repository -> String -> String -> FileVersion
FileVersion
              { fileVersionActionId :: Key Action
fileVersionActionId = Key Action
actionKey
              , fileVersionRepositoryId :: Key Repository
fileVersionRepositoryId = Key Repository
repositoryKey
              , fileVersionPath :: String
fileVersionPath = String
path
              , fileVersionCommitSha :: String
fileVersionCommitSha = String
nonGitFileVersion
              }
        FileVersionId
fileVersionKey <- FileVersion -> ReaderT SqlBackend m FileVersionId
forall backend (m :: * -> *) record.
(PersistStoreWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
record -> ReaderT backend m (Key record)
insert FileVersion
fileVersionValue
        Entity FileVersion -> DBMonad m (Entity FileVersion)
forall (m :: * -> *) a. Monad m => a -> m a
return (Entity FileVersion -> DBMonad m (Entity FileVersion))
-> Entity FileVersion -> DBMonad m (Entity FileVersion)
forall a b. (a -> b) -> a -> b
$ FileVersionId -> FileVersion -> Entity FileVersion
forall record. Key record -> record -> Entity record
Entity FileVersionId
fileVersionKey FileVersion
fileVersionValue

lastFileVersion :: MonadIO m
                => FilePath -> DBMonad m (Maybe (Entity FileVersion))
lastFileVersion :: String -> DBMonad m (Maybe (Entity FileVersion))
lastFileVersion path :: String
path =
  [Filter FileVersion]
-> [SelectOpt FileVersion]
-> DBMonad m (Maybe (Entity FileVersion))
forall backend (m :: * -> *) record.
(PersistQueryRead backend, MonadIO m,
 PersistRecordBackend record backend) =>
[Filter record]
-> [SelectOpt record] -> ReaderT backend m (Maybe (Entity record))
selectFirst [ EntityField FileVersion String
forall typ. (typ ~ String) => EntityField FileVersion typ
FileVersionPath EntityField FileVersion String -> String -> Filter FileVersion
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
==. String
path
              , EntityField FileVersion String
forall typ. (typ ~ String) => EntityField FileVersion typ
FileVersionCommitSha EntityField FileVersion String -> String -> Filter FileVersion
forall v typ.
PersistField typ =>
EntityField v typ -> typ -> Filter v
==. String
nonGitFileVersion
              ] [EntityField FileVersion FileVersionId -> SelectOpt FileVersion
forall record typ. EntityField record typ -> SelectOpt record
Desc EntityField FileVersion FileVersionId
forall typ. (typ ~ FileVersionId) => EntityField FileVersion typ
FileVersionId]

repositoryFirstOrCreate :: MonadIO m => DBMonad m (Entity Repository)
repositoryFirstOrCreate :: DBMonad m (Entity Repository)
repositoryFirstOrCreate = do
  Maybe (Entity Repository)
repositoryM <- [Filter Repository]
-> [SelectOpt Repository]
-> ReaderT SqlBackend m (Maybe (Entity Repository))
forall backend (m :: * -> *) record.
(PersistQueryRead backend, MonadIO m,
 PersistRecordBackend record backend) =>
[Filter record]
-> [SelectOpt record] -> ReaderT backend m (Maybe (Entity record))
selectFirst [] []
  case Maybe (Entity Repository)
repositoryM of
    Just repository :: Entity Repository
repository -> Entity Repository -> DBMonad m (Entity Repository)
forall (m :: * -> *) a. Monad m => a -> m a
return Entity Repository
repository
    Nothing -> do
      Entity ownerKey :: Key OrganizationalUnit
ownerKey _ <- DBMonad m (Entity OrganizationalUnit)
forall (m :: * -> *).
MonadIO m =>
DBMonad m (Entity OrganizationalUnit)
organizationalUnitFirstOrCreate
      let repositoryValue :: Repository
repositoryValue = $WRepository :: Key OrganizationalUnit -> Repository
Repository { repositoryOwnerId :: Key OrganizationalUnit
repositoryOwnerId = Key OrganizationalUnit
ownerKey }
      Key Repository
repositoryKey <- Repository -> ReaderT SqlBackend m (Key Repository)
forall backend (m :: * -> *) record.
(PersistStoreWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
record -> ReaderT backend m (Key record)
insert Repository
repositoryValue
      Entity Repository -> DBMonad m (Entity Repository)
forall (m :: * -> *) a. Monad m => a -> m a
return (Entity Repository -> DBMonad m (Entity Repository))
-> Entity Repository -> DBMonad m (Entity Repository)
forall a b. (a -> b) -> a -> b
$ Key Repository -> Repository -> Entity Repository
forall record. Key record -> record -> Entity record
Entity Key Repository
repositoryKey Repository
repositoryValue

organizationalUnitFirstOrCreate :: MonadIO m
                                => DBMonad m (Entity OrganizationalUnit)
organizationalUnitFirstOrCreate :: DBMonad m (Entity OrganizationalUnit)
organizationalUnitFirstOrCreate = do
  Maybe (Entity OrganizationalUnit)
organizationalUnitM <- [Filter OrganizationalUnit]
-> [SelectOpt OrganizationalUnit]
-> ReaderT SqlBackend m (Maybe (Entity OrganizationalUnit))
forall backend (m :: * -> *) record.
(PersistQueryRead backend, MonadIO m,
 PersistRecordBackend record backend) =>
[Filter record]
-> [SelectOpt record] -> ReaderT backend m (Maybe (Entity record))
selectFirst [] []
  case Maybe (Entity OrganizationalUnit)
organizationalUnitM of
    Just organizationalUnit :: Entity OrganizationalUnit
organizationalUnit -> Entity OrganizationalUnit -> DBMonad m (Entity OrganizationalUnit)
forall (m :: * -> *) a. Monad m => a -> m a
return Entity OrganizationalUnit
organizationalUnit
    Nothing -> do
      let organizationalUnitValue :: OrganizationalUnit
organizationalUnitValue = $WOrganizationalUnit :: String -> String -> OrganizationalUnit
OrganizationalUnit
            { organizationalUnitKind :: String
organizationalUnitKind = "Organization"
            , organizationalUnitSlug :: String
organizationalUnitSlug = "dummy"
            }
      Key OrganizationalUnit
organizationalUnitKey <- OrganizationalUnit -> ReaderT SqlBackend m (Key OrganizationalUnit)
forall backend (m :: * -> *) record.
(PersistStoreWrite backend, MonadIO m,
 PersistRecordBackend record backend) =>
record -> ReaderT backend m (Key record)
insert OrganizationalUnit
organizationalUnitValue
      Entity OrganizationalUnit -> DBMonad m (Entity OrganizationalUnit)
forall (m :: * -> *) a. Monad m => a -> m a
return (Entity OrganizationalUnit
 -> DBMonad m (Entity OrganizationalUnit))
-> Entity OrganizationalUnit
-> DBMonad m (Entity OrganizationalUnit)
forall a b. (a -> b) -> a -> b
$ Key OrganizationalUnit
-> OrganizationalUnit -> Entity OrganizationalUnit
forall record. Key record -> record -> Entity record
Entity Key OrganizationalUnit
organizationalUnitKey OrganizationalUnit
organizationalUnitValue