{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveGeneric #-}

module Database.Bolt.Extras.Internal.Persisted
  (
    BoltId
  , Persisted (..)
  , GetBoltId (..)
  , fromInt
  ) where

import           Data.Aeson        (FromJSON (..), ToJSON (..),
                                    genericParseJSON, genericToJSON)
import           Data.Aeson.Casing (aesonPrefix, snakeCase)
import           Database.Bolt     (Node (..), Relationship (..),
                                    URelationship (..))
import           GHC.Generics      (Generic (..))

-- | 'BoltId' is alias for Bolt 'Node', 'Relationship' and 'URelationship' identities.
--
type BoltId = Int

-- | 'Persisted' is wrapper for some object that can be identified with 'BoltId'.
--
data Persisted a = Persisted { Persisted a -> BoltId
objectId    :: BoltId
                             , Persisted a -> a
objectValue :: a
                             } deriving (BoltId -> Persisted a -> ShowS
[Persisted a] -> ShowS
Persisted a -> String
(BoltId -> Persisted a -> ShowS)
-> (Persisted a -> String)
-> ([Persisted a] -> ShowS)
-> Show (Persisted a)
forall a. Show a => BoltId -> Persisted a -> ShowS
forall a. Show a => [Persisted a] -> ShowS
forall a. Show a => Persisted a -> String
forall a.
(BoltId -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Persisted a] -> ShowS
$cshowList :: forall a. Show a => [Persisted a] -> ShowS
show :: Persisted a -> String
$cshow :: forall a. Show a => Persisted a -> String
showsPrec :: BoltId -> Persisted a -> ShowS
$cshowsPrec :: forall a. Show a => BoltId -> Persisted a -> ShowS
Show, a -> Persisted b -> Persisted a
(a -> b) -> Persisted a -> Persisted b
(forall a b. (a -> b) -> Persisted a -> Persisted b)
-> (forall a b. a -> Persisted b -> Persisted a)
-> Functor Persisted
forall a b. a -> Persisted b -> Persisted a
forall a b. (a -> b) -> Persisted a -> Persisted b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> Persisted b -> Persisted a
$c<$ :: forall a b. a -> Persisted b -> Persisted a
fmap :: (a -> b) -> Persisted a -> Persisted b
$cfmap :: forall a b. (a -> b) -> Persisted a -> Persisted b
Functor, Persisted a -> Persisted a -> Bool
(Persisted a -> Persisted a -> Bool)
-> (Persisted a -> Persisted a -> Bool) -> Eq (Persisted a)
forall a. Eq a => Persisted a -> Persisted a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Persisted a -> Persisted a -> Bool
$c/= :: forall a. Eq a => Persisted a -> Persisted a -> Bool
== :: Persisted a -> Persisted a -> Bool
$c== :: forall a. Eq a => Persisted a -> Persisted a -> Bool
Eq, Eq (Persisted a)
Eq (Persisted a)
-> (Persisted a -> Persisted a -> Ordering)
-> (Persisted a -> Persisted a -> Bool)
-> (Persisted a -> Persisted a -> Bool)
-> (Persisted a -> Persisted a -> Bool)
-> (Persisted a -> Persisted a -> Bool)
-> (Persisted a -> Persisted a -> Persisted a)
-> (Persisted a -> Persisted a -> Persisted a)
-> Ord (Persisted a)
Persisted a -> Persisted a -> Bool
Persisted a -> Persisted a -> Ordering
Persisted a -> Persisted a -> Persisted a
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (Persisted a)
forall a. Ord a => Persisted a -> Persisted a -> Bool
forall a. Ord a => Persisted a -> Persisted a -> Ordering
forall a. Ord a => Persisted a -> Persisted a -> Persisted a
min :: Persisted a -> Persisted a -> Persisted a
$cmin :: forall a. Ord a => Persisted a -> Persisted a -> Persisted a
max :: Persisted a -> Persisted a -> Persisted a
$cmax :: forall a. Ord a => Persisted a -> Persisted a -> Persisted a
>= :: Persisted a -> Persisted a -> Bool
$c>= :: forall a. Ord a => Persisted a -> Persisted a -> Bool
> :: Persisted a -> Persisted a -> Bool
$c> :: forall a. Ord a => Persisted a -> Persisted a -> Bool
<= :: Persisted a -> Persisted a -> Bool
$c<= :: forall a. Ord a => Persisted a -> Persisted a -> Bool
< :: Persisted a -> Persisted a -> Bool
$c< :: forall a. Ord a => Persisted a -> Persisted a -> Bool
compare :: Persisted a -> Persisted a -> Ordering
$ccompare :: forall a. Ord a => Persisted a -> Persisted a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (Persisted a)
Ord, ReadPrec [Persisted a]
ReadPrec (Persisted a)
BoltId -> ReadS (Persisted a)
ReadS [Persisted a]
(BoltId -> ReadS (Persisted a))
-> ReadS [Persisted a]
-> ReadPrec (Persisted a)
-> ReadPrec [Persisted a]
-> Read (Persisted a)
forall a. Read a => ReadPrec [Persisted a]
forall a. Read a => ReadPrec (Persisted a)
forall a. Read a => BoltId -> ReadS (Persisted a)
forall a. Read a => ReadS [Persisted a]
forall a.
(BoltId -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Persisted a]
$creadListPrec :: forall a. Read a => ReadPrec [Persisted a]
readPrec :: ReadPrec (Persisted a)
$creadPrec :: forall a. Read a => ReadPrec (Persisted a)
readList :: ReadS [Persisted a]
$creadList :: forall a. Read a => ReadS [Persisted a]
readsPrec :: BoltId -> ReadS (Persisted a)
$creadsPrec :: forall a. Read a => BoltId -> ReadS (Persisted a)
Read, (forall x. Persisted a -> Rep (Persisted a) x)
-> (forall x. Rep (Persisted a) x -> Persisted a)
-> Generic (Persisted a)
forall x. Rep (Persisted a) x -> Persisted a
forall x. Persisted a -> Rep (Persisted a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Persisted a) x -> Persisted a
forall a x. Persisted a -> Rep (Persisted a) x
$cto :: forall a x. Rep (Persisted a) x -> Persisted a
$cfrom :: forall a x. Persisted a -> Rep (Persisted a) x
Generic)

-- | This is just check that your 'BoltId' is valid.
--
fromInt :: Int -> BoltId
fromInt :: BoltId -> BoltId
fromInt BoltId
i | BoltId
i BoltId -> BoltId -> Bool
forall a. Ord a => a -> a -> Bool
>= BoltId
0    = BoltId
i
          | Bool
otherwise = String -> BoltId
forall a. HasCallStack => String -> a
error String
"Database.Bolt.Extras.Internal.Persisted: could not create BoltId with identity less then zero."

-- | Common class to get 'BoltId' from the object.
--
class GetBoltId a where
  getBoltId :: a -> BoltId

instance GetBoltId Node where
  getBoltId :: Node -> BoltId
getBoltId = BoltId -> BoltId
fromInt (BoltId -> BoltId) -> (Node -> BoltId) -> Node -> BoltId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Node -> BoltId
nodeIdentity

instance GetBoltId Relationship where
  getBoltId :: Relationship -> BoltId
getBoltId = BoltId -> BoltId
fromInt (BoltId -> BoltId)
-> (Relationship -> BoltId) -> Relationship -> BoltId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Relationship -> BoltId
relIdentity

instance GetBoltId URelationship where
  getBoltId :: URelationship -> BoltId
getBoltId = BoltId -> BoltId
fromInt (BoltId -> BoltId)
-> (URelationship -> BoltId) -> URelationship -> BoltId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. URelationship -> BoltId
urelIdentity

instance GetBoltId (Persisted a) where
  getBoltId :: Persisted a -> BoltId
getBoltId = BoltId -> BoltId
fromInt (BoltId -> BoltId)
-> (Persisted a -> BoltId) -> Persisted a -> BoltId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Persisted a -> BoltId
forall a. Persisted a -> BoltId
objectId

instance ToJSON a => ToJSON (Persisted a) where
  toJSON :: Persisted a -> Value
toJSON = Options -> Persisted a -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON (Options -> Persisted a -> Value)
-> Options -> Persisted a -> Value
forall a b. (a -> b) -> a -> b
$ ShowS -> Options
aesonPrefix ShowS
snakeCase

instance FromJSON a => FromJSON (Persisted a) where
  parseJSON :: Value -> Parser (Persisted a)
parseJSON = Options -> Value -> Parser (Persisted a)
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON (Options -> Value -> Parser (Persisted a))
-> Options -> Value -> Parser (Persisted a)
forall a b. (a -> b) -> a -> b
$ ShowS -> Options
aesonPrefix ShowS
snakeCase