module Gis.Saga.Cmd where import Data.Map (elems) import qualified Data.Map as M import Data.Maybe (fromMaybe, fromJust) import GHC.IO.Exception import Gis.Saga.Types import Gis.Saga.Utils import System.Process (system) import System.Posix.Temp (mkdtemp) import System.FilePath.Posix (replaceDirectory, joinPath) import System.Directory (getTemporaryDirectory) -- | Actual Program to do the work progName :: String progName = "saga_cmd" -- | Call saga with a specific configuration doSaga :: SagaCmd -> IO FilePath doSaga (SagaCmd lib mod (kIn, kOut) ps maybePre maybePost fOut fIn) = do pre fIn fOut r <- saga lib mod (elems ps ++ [(kIn,fIn),(kOut,fOut)]) case r of ExitSuccess -> do post fIn fOut return fOut ExitFailure _ -> error "saga_cmd failed" where pre = fromMaybe nthn maybePre post = fromMaybe nthn maybePost nthn _ _ = return () -- | Wrapper around saga saga :: String -- ^ Library name -> String -- ^ Module name -> [(String,String)] -- ^ Parameter key-value -> IO ExitCode -- ^ Output-file saga lib mod params = do putStrLn cmd system cmd where renderParams = map renderPara renderPara (k,v) = "-" ++ k ++ "=" ++ v cmd = unwords [ progName ,lib ,mod ,unwords . renderParams $ params ] -- | adjust default parameters with the ones given on the command-line adjustSagaCmdParas :: CmdPars -> SagaCmd -> SagaCmd adjustSagaCmdParas cmdPrs cmd@(SagaCmd{sParas = libPrs}) = cmd {sParas = adjustParas libPrs cmdPrs} -- | Overwrite default parameters with parameters given on the command-line adjustParas :: ParaMap -- ^ parameters specified in 'SagaCmd' -> CmdPars -- ^ parameters given on the cmd-line -> ParaMap -- ^ adjusted parameters adjustParas libPrs cmdPrs = M.mapWithKey lkp m' where -- | union of cmd-pars and lib-pars; this overwrites the defaults m = M.union cmdPrs $ M.map snd libPrs -- | select relevant pars m' = M.filterWithKey (\k _ -> k `elem` M.keys libPrs) m lkp k v = (fst $ fromJust (M.lookup k libPrs), v) -- | Execute a 'SagaIoCmdExt' doCmdChain :: [SagaIoCmdExt] -> CmdPars -> FilePath -> Maybe FilePath -> IO FilePath doCmdChain chain pars fIn fOut = do let outFsDefault = tail $ scanl appendFileName fIn (map snd chain) outFs <- case fOut of Nothing -> return outFsDefault Just f -> do dtempDir <- getTemporaryDirectory let dtempT = joinPath [dtempDir, "sagaPipe"] dtemp <- mkdtemp dtempT return $ map (`replaceDirectory` dtemp) (init outFsDefault) ++ [f] let chain' = map (\(f,ext) -> f ext) $ zip (map fst chain) outFs foldl (\fOut f -> do fIn' <- fOut doSaga . adjustSagaCmdParas pars . f $ fIn' ) (return fIn) chain' -- | Lookup a chain lkpChain :: SagaIoCmdDB -> [String] -> [SagaIoCmdExt] lkpChain db = map (`lkpCmd` db) -- | Lookup a single command lkpCmd :: String -> SagaIoCmdDB -> SagaIoCmdExt lkpCmd s db = fromMaybe (error "Command is not yet implemented") $ M.lookup s db