-- | This module provides functions to translate errors into strings.
module Text.XML.Light.Extractors.ShowErr
  ( showExtractionErr
  , showErr
  , showPath
  )
where

import Data.List

import           Text.XML.Light.Types
import qualified Text.XML.Light.Output as XML
import           Text.XML.Light.Extractors.Internal (ExtractionErr(..), Err(..), Path)


-- | Converts an extraction error to a multi line string message.
--
-- Paths are shown according to 'showPath'.
showExtractionErr :: ExtractionErr -> String
showExtractionErr :: ExtractionErr -> String
showExtractionErr (ExtractionErr Err
e Path
path) =
  Path -> String
unlines [Err -> String
showErr Err
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"in path: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Path -> String
showPath Path
path]


-- | Paths will show like this:
--
-- @1\/foo\/2\/bar\/\@x@
--
-- which represents the \"x\" attribute of the \"bar\" element, which
-- is the second content of the \"foo\" element which is the first
-- content from the root.
showPath :: Path -> String
showPath :: Path -> String
showPath = String -> Path -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"/" (Path -> String) -> (Path -> Path) -> Path -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Path -> Path
forall a. [a] -> [a]
reverse


showErr :: Err -> String
showErr :: Err -> String
showErr (ErrExpectContent String
expect Content
found) =
  Path -> String
unlines
  [ Path -> String
unwords [String
"Expected:", String
expect]
  , Path -> String
unwords [String
"Found:", Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
60 (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Content -> String
XML.showContent Content
found]
  , Path -> String
unwords [String
"at line:", Content -> String
showLine Content
found]
  ]
showErr (ErrExpectAttrib String
expect Element
parent) =
  Path -> String
unlines
  [ Path -> String
unwords [String
"Missing attribute", String -> String
forall a. Show a => a -> String
show String
expect, String
"of", String -> String
forall a. Show a => a -> String
show (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ QName -> String
qName (QName -> String) -> QName -> String
forall a b. (a -> b) -> a -> b
$ Element -> QName
elName Element
parent]
  , Path -> String
unwords [String
"at line:", Content -> String
showLine (Content -> String) -> Content -> String
forall a b. (a -> b) -> a -> b
$ Element -> Content
Elem Element
parent]
  ]
showErr (ErrAttribValue String
expect String
found Element
parent) =
  Path -> String
unlines
  [ Path -> String
unwords [String
"Expected:", String
expect]
  , Path -> String
unwords [String
"Found:", String -> String
forall a. Show a => a -> String
show String
found]
  , Path -> String
unwords [String
"line:", Content -> String
showLine (Content -> String) -> Content -> String
forall a b. (a -> b) -> a -> b
$ Element -> Content
Elem Element
parent]
  ]
showErr (ErrMsg String
msg) =
  Path -> String
unlines [String
msg]

showErr (ErrNull String
expected) = 
  Path -> String
unlines [Path -> String
unwords [String
"Expected:", String
expected]]

showErr (ErrEnd Content
found) =
  Path -> String
unlines [Path -> String
unwords [String
"Unexpected:", Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
60 (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Content -> String
XML.showContent Content
found]]


contentLine :: Content -> Maybe Integer
contentLine :: Content -> Maybe Integer
contentLine (Elem Element
e) = Element -> Maybe Integer
elLine Element
e
contentLine (Text CData
t) = CData -> Maybe Integer
cdLine CData
t
contentLine Content
_        = Maybe Integer
forall a. Maybe a
Nothing

showLine :: Content -> String
showLine :: Content -> String
showLine = String -> (Integer -> String) -> Maybe Integer -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
"??" Integer -> String
forall a. Show a => a -> String
show (Maybe Integer -> String)
-> (Content -> Maybe Integer) -> Content -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Content -> Maybe Integer
contentLine