{-# LANGUAGE OverloadedStrings #-} module Database.Neo4j.Property where import Control.Exception.Lifted (throw, catch) import qualified Data.Aeson as J import qualified Data.HashMap.Lazy as M import qualified Data.Text as T import qualified Data.Text.Encoding as TE import Database.Neo4j.Types import Database.Neo4j.Http -- | Retrieve relationship/node properties from the DB, if the entity is not present it will raise an exception -- If the entity doesn't exist it will raise a Neo4jNoEntity exception getProperties :: Entity a => a -> Neo4j Properties getProperties e = Neo4j $ \conn -> httpRetrieveSure conn (propertyPath e) `catch` proc404Exc e -- | Get a relationship/node property -- If the 404 is because the parent entity doesn't exist we'll raise the corresponding Neo4jNoEntity -- If the 404 is because there is no property just return Nothing getProperty :: Entity a => a -> T.Text -> Neo4j (Maybe PropertyValue) getProperty e prop = Neo4j $ \conn -> do res <- httpRetrieveValue conn path case res of Right value -> return value Left expl -> if expl `elem` excList then throw (Neo4jNoEntityException $ entityPath e) else return Nothing where path = propertyPath e <> "/" <> TE.encodeUtf8 prop excList = ["RelationshipNotFoundException", "NodeNotFoundException"] -- | Set all relationship/node properties -- If the entity doesn't exist it will raise a Neo4jNoEntity exception setProperties :: Entity a => a -> Properties -> Neo4j a setProperties e props = Neo4j $ \conn -> (do httpModify conn (propertyPath e) $ J.encode props return $ setEntityProperties e props) `catch` proc404Exc e -- | Set a relationship/node property -- If the entity doesn't exist it will raise a Neo4jNoEntity exception setProperty :: Entity a => a -> T.Text -> PropertyValue -> Neo4j a setProperty e name value = Neo4j $ \conn -> (do httpModify conn (propertyPath e <> "/" <> TE.encodeUtf8 name) $ J.encode value return $ setEntityProperties e $ M.insert name value (getEntityProperties e)) `catch` proc404Exc e -- | Delete all relationship/node properties -- If the entity doesn't exist it will raise a Neo4jNoEntity exception deleteProperties :: Entity a => a -> Neo4j a deleteProperties e = Neo4j $ \conn -> (do httpDeleteNo404 conn (propertyPath e) return $ setEntityProperties e emptyProperties) `catch` proc404Exc e -- | Delete a relationship/node property -- If the entity doesn't exist it will raise a Neo4jNoEntity exception deleteProperty :: Entity a => a -> T.Text -> Neo4j a deleteProperty e name = Neo4j $ \conn -> do res <- httpDelete404Explained conn (propertyPath e <> "/" <> TE.encodeUtf8 name) case res of Right _ -> return resultingProps Left expl -> if expl `elem` excList then throw (Neo4jNoEntityException $ entityPath e) else return resultingProps where excList = ["RelationshipNotFoundException", "NodeNotFoundException"] resultingProps = setEntityProperties e $ M.delete name (getEntityProperties e)