module Database.Neo4j.Relationship where
import Control.Exception.Lifted (throw, catch)
import Data.Aeson ((.=))
import Data.Maybe (fromMaybe)
import qualified Data.Aeson as J
import qualified Data.ByteString as S
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import qualified Network.HTTP.Types as HT
import Database.Neo4j.Node
import Database.Neo4j.Http
import Database.Neo4j.Types
relId :: Relationship -> S.ByteString
relId n = S.drop (pathLength + 1) (runRelIdentifier n)
where pathLength = S.length relationshipAPI
allRelationshipTypes :: Neo4j [RelationshipType]
allRelationshipTypes = Neo4j $ \conn -> httpRetrieveSure conn "/db/data/relationship/types"
createRelationship :: RelationshipType -> Properties -> Node -> Node -> Neo4j Relationship
createRelationship t props nodefrom nodeto = Neo4j $ \conn -> do
res <- httpCreate4XXExplained conn reqPath reqBody
case res of
Right rel -> return rel
Left expl -> wrapExc expl
where reqPath = runNodeIdentifier nodefrom <> "/relationships"
reqBody = J.encode $ J.object ["to" .= runNodePath (nodePath nodeto), "type" .= t,
"data" .= J.toJSON props]
wrapExc msg
| msg == "StartNodeNotFoundException" = throw (Neo4jNoEntityException $ runNodeIdentifier nodefrom)
| msg == "EndNodeNotFoundException" = throw (Neo4jNoEntityException $ runNodeIdentifier nodeto)
| otherwise = throw (Neo4jHttpException $ T.unpack msg)
getRelationship :: RelIdentifier a => a -> Neo4j (Maybe Relationship)
getRelationship rel = Neo4j $ \conn -> httpRetrieve conn (runRelIdentifier rel)
getRelationshipFrom :: Relationship -> Neo4j Node
getRelationshipFrom rel = getNode node >>= processMaybe
where node = relFrom rel
processMaybe n = return $ fromMaybe (throw $ Neo4jNoEntityException (runNodeIdentifier node)) n
getRelationshipTo :: Relationship -> Neo4j Node
getRelationshipTo rel = getNode node >>= processMaybe
where node = relTo rel
processMaybe n = return $ fromMaybe (throw $ Neo4jNoEntityException (runNodeIdentifier node)) n
deleteRelationship :: RelIdentifier a => a -> Neo4j ()
deleteRelationship rel = Neo4j $ \conn -> httpDelete conn (runRelIdentifier rel)
getRelationships :: Node -> Direction -> [RelationshipType] -> Neo4j [Relationship]
getRelationships n dir types = Neo4j $ \conn ->
httpRetrieveSure conn (runNodeIdentifier n <> "/relationships/" <> dirStr dir <> filterStr types) `catch` procExc
where dirStr Outgoing = "out"
dirStr Incoming = "in"
dirStr Any = "all"
filterStr [] = ""
filterStr f = "/" <> TE.encodeUtf8 (T.intercalate "%26" f)
procExc exc@(Neo4jUnexpectedResponseException s)
| s == HT.status404 = throw (Neo4jNoEntityException $ runNodeIdentifier n)
| otherwise = throw exc
procExc exc = throw exc