module Text.XML.HXT.Arrow.XmlState.ErrorHandling
where
import Control.Arrow
import Control.Arrow.ArrowList
import Control.Arrow.ArrowIf
import Control.Arrow.ArrowTree
import Control.Arrow.ArrowIO
import Control.Exception ( SomeException )
import Data.Maybe
import Text.XML.HXT.DOM.Interface
import Text.XML.HXT.Arrow.XmlArrow
import Text.XML.HXT.Arrow.XmlState.TypeDefs
import System.IO ( hPutStrLn
, hFlush
, stderr
)
changeErrorStatus :: (Int -> Int -> Int) -> IOStateArrow s Int Int
changeErrorStatus f = chgSysVar theErrorStatus f
clearErrStatus :: IOStateArrow s b b
clearErrStatus = configSysVar $ setS theErrorStatus 0
setErrStatus :: IOStateArrow s Int Int
setErrStatus = changeErrorStatus max
getErrStatus :: IOStateArrow s XmlTree Int
getErrStatus = getSysVar theErrorStatus
setErrMsgStatus :: IOStateArrow s XmlTree XmlTree
setErrMsgStatus = perform
( getErrorLevel >>> setErrStatus )
setErrorMsgHandler :: Bool -> (String -> IO ()) -> IOStateArrow s b b
setErrorMsgHandler c f = configSysVar $ setS (theErrorMsgCollect .&&&. theErrorMsgHandler) (c, f)
sysErrorMsg :: IOStateArrow s XmlTree XmlTree
sysErrorMsg = perform
( getErrorLevel &&& getErrorMsg
>>>
arr formatErrorMsg
>>>
getSysVar theErrorMsgHandler &&& this
>>>
arrIO (\ (h, msg) -> h msg)
)
where
formatErrorMsg (level, msg) = "\n" ++ errClass level ++ ": " ++ msg
errClass l = fromMaybe "fatal error" . lookup l $ msgList
where
msgList = [ (c_ok, "no error")
, (c_warn, "warning")
, (c_err, "error")
, (c_fatal, "fatal error")
]
errorMsgStderr :: IOStateArrow s b b
errorMsgStderr = setErrorMsgHandler False (\ x ->
do hPutStrLn stderr x
hFlush stderr
)
errorMsgCollect :: IOStateArrow s b b
errorMsgCollect = setErrorMsgHandler True (const $ return ())
errorMsgStderrAndCollect :: IOStateArrow s b b
errorMsgStderrAndCollect = setErrorMsgHandler True (hPutStrLn stderr)
errorMsgIgnore :: IOStateArrow s b b
errorMsgIgnore = setErrorMsgHandler False (const $ return ())
getErrorMessages :: IOStateArrow s b XmlTree
getErrorMessages = getSysVar theErrorMsgList
>>>
configSysVar (setS theErrorMsgList [])
>>>
arrL reverse
addToErrorMsgList :: IOStateArrow s XmlTree XmlTree
addToErrorMsgList = chgSysVar
( theErrorMsgCollect .&&&. theErrorMsgList )
( \ e (cs, es) -> (cs, if cs then e : es else es) )
filterErrorMsg :: IOStateArrow s XmlTree XmlTree
filterErrorMsg = ( setErrMsgStatus
>>>
sysErrorMsg
>>>
addToErrorMsgList
>>>
none
)
`when`
isError
issueWarn :: String -> IOStateArrow s b b
issueWarn msg = perform (warn msg >>> filterErrorMsg)
issueErr :: String -> IOStateArrow s b b
issueErr msg = perform (err msg >>> filterErrorMsg)
issueFatal :: String -> IOStateArrow s b b
issueFatal msg = perform (fatal msg >>> filterErrorMsg)
issueExc :: String -> IOStateArrow s SomeException b
issueExc m = ( issueFatal $< arr ((msg ++) . show) )
>>>
none
where
msg | null m = "Exception: "
| otherwise = "Exception in " ++ m ++ ": "
setDocumentStatus :: Int -> String -> IOStateArrow s XmlTree XmlTree
setDocumentStatus level msg
= ( addAttrl ( sattr a_status (show level)
<+>
sattr a_module msg
)
>>>
( if level >= c_err
then setChildren []
else this
)
)
`when`
isRoot
setDocumentStatusFromSystemState :: String -> IOStateArrow s XmlTree XmlTree
setDocumentStatusFromSystemState msg
= setStatus $< getErrStatus
where
setStatus level
| level <= c_warn = this
| otherwise = setDocumentStatus level msg
documentStatusOk :: ArrowXml a => a XmlTree XmlTree
documentStatusOk = isRoot
>>>
( (getAttrValue a_status
>>>
isA (\ v -> null v || ((read v)::Int) <= c_warn)
)
`guards`
this
)
errorOutputToStderr :: String -> IO ()
errorOutputToStderr msg
= do
hPutStrLn stderr msg
hFlush stderr