module Graql.Shell ( Concept , Result , cid , ctype , value , runFile , runMatch , migrateCsv ) where import Control.Applicative (empty) import Data.Aeson (FromJSON, eitherDecodeStrict, parseJSON, (.:), (.:?)) import qualified Data.Aeson as Aeson import Data.Map (Map) import Data.Text (Text, pack) import Data.Text.Encoding (encodeUtf8) import Graql hiding ((.:)) import System.Process (callProcess, readProcessWithExitCode) -- |A concept in the graph data Concept = Concept { cid :: Text, cname :: Maybe Name, ctype :: Maybe Name, value :: Maybe Value } deriving Show -- |A result of a match query, binding variables to concepts type Result = Map Var Concept -- |Run the given file path on the database, ignoring the output runFile :: FilePath -> IO () runFile path = callProcess "graql.sh" ["-f", path] -- |Run a match query on the graph runMatch :: MatchQuery -> IO [Result] runMatch q = do result <- parseResults <$> runGraql q either fail return result -- |Run the CSV migrator using the given csv file, template file and separator migrateCsv :: FilePath -> FilePath -> String -> IO () migrateCsv file template separator = callProcess "migration.sh" args where args = ["csv", "-i", file, "-t", template, "-s", separator] type Error = String runGraql :: MatchQuery -> IO String runGraql q = do (_, stdout, stderr) <- readProcessWithExitCode "graql.sh" args "" if length (lines stderr) <= 1 then return stdout else fail stderr where args = ["-e", show q, "-o", "json"] parseResults :: String -> Either Error [Result] parseResults = mapM parseResult . lines parseResult :: String -> Either Error Result parseResult = eitherDecodeStrict . encodeUtf8 . pack instance FromJSON Concept where parseJSON (Aeson.Object obj) = Concept <$> (obj .: "id") <*> (obj .:? "name") <*> (obj .:? "isa") <*> (obj .:? "value") parseJSON _ = empty