{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, FlexibleContexts #-}
-- | Type classes to allow for XML handling functions to be generalized to
-- work with different document types.
module Text.XML.Expat.Internal.DocumentClass where

import Text.XML.Expat.Internal.NodeClass (NodeClass)
import Control.DeepSeq
import Control.Monad (mzero)
import Data.List.Class (List)


-- | XML declaration, consisting of version, encoding and standalone.
--
-- The formatting functions always outputs only UTF-8, regardless
-- of what encoding is specified here.  If you want to produce a document in a
-- different encoding, then set the encoding here, format the document, and then
-- convert the output text from UTF-8 to your desired encoding using some
-- text conversion library.
data XMLDeclaration text = XMLDeclaration text (Maybe text) (Maybe Bool) deriving (XMLDeclaration text -> XMLDeclaration text -> Bool
(XMLDeclaration text -> XMLDeclaration text -> Bool)
-> (XMLDeclaration text -> XMLDeclaration text -> Bool)
-> Eq (XMLDeclaration text)
forall text.
Eq text =>
XMLDeclaration text -> XMLDeclaration text -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall text.
Eq text =>
XMLDeclaration text -> XMLDeclaration text -> Bool
== :: XMLDeclaration text -> XMLDeclaration text -> Bool
$c/= :: forall text.
Eq text =>
XMLDeclaration text -> XMLDeclaration text -> Bool
/= :: XMLDeclaration text -> XMLDeclaration text -> Bool
Eq, Int -> XMLDeclaration text -> ShowS
[XMLDeclaration text] -> ShowS
XMLDeclaration text -> String
(Int -> XMLDeclaration text -> ShowS)
-> (XMLDeclaration text -> String)
-> ([XMLDeclaration text] -> ShowS)
-> Show (XMLDeclaration text)
forall text. Show text => Int -> XMLDeclaration text -> ShowS
forall text. Show text => [XMLDeclaration text] -> ShowS
forall text. Show text => XMLDeclaration text -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall text. Show text => Int -> XMLDeclaration text -> ShowS
showsPrec :: Int -> XMLDeclaration text -> ShowS
$cshow :: forall text. Show text => XMLDeclaration text -> String
show :: XMLDeclaration text -> String
$cshowList :: forall text. Show text => [XMLDeclaration text] -> ShowS
showList :: [XMLDeclaration text] -> ShowS
Show)

-- | Stub for future expansion.
data DocumentTypeDeclaration (c :: * -> *) tag text = DocumentTypeDeclaration deriving (DocumentTypeDeclaration c tag text
-> DocumentTypeDeclaration c tag text -> Bool
(DocumentTypeDeclaration c tag text
 -> DocumentTypeDeclaration c tag text -> Bool)
-> (DocumentTypeDeclaration c tag text
    -> DocumentTypeDeclaration c tag text -> Bool)
-> Eq (DocumentTypeDeclaration c tag text)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (c :: * -> *) tag text.
DocumentTypeDeclaration c tag text
-> DocumentTypeDeclaration c tag text -> Bool
$c== :: forall (c :: * -> *) tag text.
DocumentTypeDeclaration c tag text
-> DocumentTypeDeclaration c tag text -> Bool
== :: DocumentTypeDeclaration c tag text
-> DocumentTypeDeclaration c tag text -> Bool
$c/= :: forall (c :: * -> *) tag text.
DocumentTypeDeclaration c tag text
-> DocumentTypeDeclaration c tag text -> Bool
/= :: DocumentTypeDeclaration c tag text
-> DocumentTypeDeclaration c tag text -> Bool
Eq, Int -> DocumentTypeDeclaration c tag text -> ShowS
[DocumentTypeDeclaration c tag text] -> ShowS
DocumentTypeDeclaration c tag text -> String
(Int -> DocumentTypeDeclaration c tag text -> ShowS)
-> (DocumentTypeDeclaration c tag text -> String)
-> ([DocumentTypeDeclaration c tag text] -> ShowS)
-> Show (DocumentTypeDeclaration c tag text)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (c :: * -> *) tag text.
Int -> DocumentTypeDeclaration c tag text -> ShowS
forall (c :: * -> *) tag text.
[DocumentTypeDeclaration c tag text] -> ShowS
forall (c :: * -> *) tag text.
DocumentTypeDeclaration c tag text -> String
$cshowsPrec :: forall (c :: * -> *) tag text.
Int -> DocumentTypeDeclaration c tag text -> ShowS
showsPrec :: Int -> DocumentTypeDeclaration c tag text -> ShowS
$cshow :: forall (c :: * -> *) tag text.
DocumentTypeDeclaration c tag text -> String
show :: DocumentTypeDeclaration c tag text -> String
$cshowList :: forall (c :: * -> *) tag text.
[DocumentTypeDeclaration c tag text] -> ShowS
showList :: [DocumentTypeDeclaration c tag text] -> ShowS
Show)

data Misc text =
    Comment !text |
    ProcessingInstruction !text !text

instance Show text => Show (Misc text) where
    showsPrec :: Int -> Misc text -> ShowS
showsPrec Int
d (ProcessingInstruction text
t text
txt) = Bool -> ShowS -> ShowS
showParen (Int
d Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
10) (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
        (String
"ProcessingInstruction "String -> ShowS
forall a. [a] -> [a] -> [a]
++) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> text -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
11 text
t ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
" "String -> ShowS
forall a. [a] -> [a] -> [a]
++) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> text -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
11 text
txt
    showsPrec Int
d (Comment text
t) = Bool -> ShowS -> ShowS
showParen (Int
d Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
10) (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ (String
"Comment "String -> ShowS
forall a. [a] -> [a] -> [a]
++) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> text -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
11 text
t

instance Eq text => Eq (Misc text) where
    ProcessingInstruction text
t1 text
d1 == :: Misc text -> Misc text -> Bool
== ProcessingInstruction text
t2 text
d2 = 
        text
t1 text -> text -> Bool
forall a. Eq a => a -> a -> Bool
== text
t2 Bool -> Bool -> Bool
&&
        text
d1 text -> text -> Bool
forall a. Eq a => a -> a -> Bool
== text
d2
    Comment text
t1 == Comment text
t2 = text
t1 text -> text -> Bool
forall a. Eq a => a -> a -> Bool
== text
t2
    Misc text
_ == Misc text
_ = Bool
False

instance NFData text => NFData (Misc text) where
    rnf :: Misc text -> ()
rnf (ProcessingInstruction text
target text
txt) = (text, text) -> ()
forall a. NFData a => a -> ()
rnf (text
target, text
txt)
    rnf (Comment text
txt) = text -> ()
forall a. NFData a => a -> ()
rnf text
txt

type family NodeType (d :: (* -> *) -> * -> * -> *) :: (* -> *) -> * -> * -> *

class (Functor c, List c, NodeClass (NodeType d) c) => DocumentClass d (c :: * -> *) where
    -- | Get the XML declaration for this document.
    getXMLDeclaration :: d c tag text -> Maybe (XMLDeclaration text)

    -- | Get the Document Type Declaration (DTD) for this document.
    getDocumentTypeDeclaration :: d c tag text -> Maybe (DocumentTypeDeclaration c tag text)

    -- | Get the top-level 'Misc' nodes for this document.
    getTopLevelMiscs :: d c tag text -> c (Misc text)

    -- | Get the root element for this document.
    getRoot :: d c tag text -> NodeType d c tag text

    -- | Make a document with the specified fields.
    mkDocument :: Maybe (XMLDeclaration text)
               -> Maybe (DocumentTypeDeclaration c tag text)
               -> c (Misc text)
               -> NodeType d c tag text
               -> d c tag text

-- | Make a document with the specified root node and all other information
-- set to defaults.
mkPlainDocument :: DocumentClass d c => NodeType d c tag text -> d c tag text
mkPlainDocument :: forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
NodeType d c tag text -> d c tag text
mkPlainDocument = Maybe (XMLDeclaration text)
-> Maybe (DocumentTypeDeclaration c tag text)
-> c (Misc text)
-> NodeType d c tag text
-> d c tag text
forall text tag.
Maybe (XMLDeclaration text)
-> Maybe (DocumentTypeDeclaration c tag text)
-> c (Misc text)
-> NodeType d c tag text
-> d c tag text
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) text tag.
DocumentClass d c =>
Maybe (XMLDeclaration text)
-> Maybe (DocumentTypeDeclaration c tag text)
-> c (Misc text)
-> NodeType d c tag text
-> d c tag text
mkDocument Maybe (XMLDeclaration text)
forall a. Maybe a
Nothing Maybe (DocumentTypeDeclaration c tag text)
forall a. Maybe a
Nothing c (Misc text)
forall a. c a
forall (m :: * -> *) a. MonadPlus m => m a
mzero

modifyXMLDeclaration :: DocumentClass d c =>
                        (Maybe (XMLDeclaration text) -> Maybe (XMLDeclaration text))
                     -> d c tag text
                     -> d c tag text
modifyXMLDeclaration :: forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) text tag.
DocumentClass d c =>
(Maybe (XMLDeclaration text) -> Maybe (XMLDeclaration text))
-> d c tag text -> d c tag text
modifyXMLDeclaration Maybe (XMLDeclaration text) -> Maybe (XMLDeclaration text)
f d c tag text
doc = Maybe (XMLDeclaration text)
-> Maybe (DocumentTypeDeclaration c tag text)
-> c (Misc text)
-> NodeType d c tag text
-> d c tag text
forall text tag.
Maybe (XMLDeclaration text)
-> Maybe (DocumentTypeDeclaration c tag text)
-> c (Misc text)
-> NodeType d c tag text
-> d c tag text
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) text tag.
DocumentClass d c =>
Maybe (XMLDeclaration text)
-> Maybe (DocumentTypeDeclaration c tag text)
-> c (Misc text)
-> NodeType d c tag text
-> d c tag text
mkDocument (Maybe (XMLDeclaration text) -> Maybe (XMLDeclaration text)
f (Maybe (XMLDeclaration text) -> Maybe (XMLDeclaration text))
-> Maybe (XMLDeclaration text) -> Maybe (XMLDeclaration text)
forall a b. (a -> b) -> a -> b
$ d c tag text -> Maybe (XMLDeclaration text)
forall tag text. d c tag text -> Maybe (XMLDeclaration text)
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
d c tag text -> Maybe (XMLDeclaration text)
getXMLDeclaration d c tag text
doc) (d c tag text -> Maybe (DocumentTypeDeclaration c tag text)
forall tag text.
d c tag text -> Maybe (DocumentTypeDeclaration c tag text)
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
d c tag text -> Maybe (DocumentTypeDeclaration c tag text)
getDocumentTypeDeclaration d c tag text
doc)
        (d c tag text -> c (Misc text)
forall tag text. d c tag text -> c (Misc text)
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
d c tag text -> c (Misc text)
getTopLevelMiscs d c tag text
doc) (d c tag text -> NodeType d c tag text
forall tag text. d c tag text -> NodeType d c tag text
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
d c tag text -> NodeType d c tag text
getRoot d c tag text
doc)

modifyDocumentTypeDeclaration :: DocumentClass d c =>
                                 (Maybe (DocumentTypeDeclaration c tag text) -> Maybe (DocumentTypeDeclaration c tag text))
                              -> d c tag text
                              -> d c tag text
modifyDocumentTypeDeclaration :: forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
(Maybe (DocumentTypeDeclaration c tag text)
 -> Maybe (DocumentTypeDeclaration c tag text))
-> d c tag text -> d c tag text
modifyDocumentTypeDeclaration Maybe (DocumentTypeDeclaration c tag text)
-> Maybe (DocumentTypeDeclaration c tag text)
f d c tag text
doc = Maybe (XMLDeclaration text)
-> Maybe (DocumentTypeDeclaration c tag text)
-> c (Misc text)
-> NodeType d c tag text
-> d c tag text
forall text tag.
Maybe (XMLDeclaration text)
-> Maybe (DocumentTypeDeclaration c tag text)
-> c (Misc text)
-> NodeType d c tag text
-> d c tag text
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) text tag.
DocumentClass d c =>
Maybe (XMLDeclaration text)
-> Maybe (DocumentTypeDeclaration c tag text)
-> c (Misc text)
-> NodeType d c tag text
-> d c tag text
mkDocument (d c tag text -> Maybe (XMLDeclaration text)
forall tag text. d c tag text -> Maybe (XMLDeclaration text)
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
d c tag text -> Maybe (XMLDeclaration text)
getXMLDeclaration d c tag text
doc) (Maybe (DocumentTypeDeclaration c tag text)
-> Maybe (DocumentTypeDeclaration c tag text)
f (Maybe (DocumentTypeDeclaration c tag text)
 -> Maybe (DocumentTypeDeclaration c tag text))
-> Maybe (DocumentTypeDeclaration c tag text)
-> Maybe (DocumentTypeDeclaration c tag text)
forall a b. (a -> b) -> a -> b
$ d c tag text -> Maybe (DocumentTypeDeclaration c tag text)
forall tag text.
d c tag text -> Maybe (DocumentTypeDeclaration c tag text)
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
d c tag text -> Maybe (DocumentTypeDeclaration c tag text)
getDocumentTypeDeclaration d c tag text
doc)
        (d c tag text -> c (Misc text)
forall tag text. d c tag text -> c (Misc text)
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
d c tag text -> c (Misc text)
getTopLevelMiscs d c tag text
doc) (d c tag text -> NodeType d c tag text
forall tag text. d c tag text -> NodeType d c tag text
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
d c tag text -> NodeType d c tag text
getRoot d c tag text
doc)

modifyTopLevelMiscs :: DocumentClass d c =>
                       (c (Misc text) -> c (Misc text))
                    -> d c tag text
                    -> d c tag text
modifyTopLevelMiscs :: forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) text tag.
DocumentClass d c =>
(c (Misc text) -> c (Misc text)) -> d c tag text -> d c tag text
modifyTopLevelMiscs c (Misc text) -> c (Misc text)
f d c tag text
doc = Maybe (XMLDeclaration text)
-> Maybe (DocumentTypeDeclaration c tag text)
-> c (Misc text)
-> NodeType d c tag text
-> d c tag text
forall text tag.
Maybe (XMLDeclaration text)
-> Maybe (DocumentTypeDeclaration c tag text)
-> c (Misc text)
-> NodeType d c tag text
-> d c tag text
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) text tag.
DocumentClass d c =>
Maybe (XMLDeclaration text)
-> Maybe (DocumentTypeDeclaration c tag text)
-> c (Misc text)
-> NodeType d c tag text
-> d c tag text
mkDocument (d c tag text -> Maybe (XMLDeclaration text)
forall tag text. d c tag text -> Maybe (XMLDeclaration text)
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
d c tag text -> Maybe (XMLDeclaration text)
getXMLDeclaration d c tag text
doc) (d c tag text -> Maybe (DocumentTypeDeclaration c tag text)
forall tag text.
d c tag text -> Maybe (DocumentTypeDeclaration c tag text)
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
d c tag text -> Maybe (DocumentTypeDeclaration c tag text)
getDocumentTypeDeclaration d c tag text
doc)
        (c (Misc text) -> c (Misc text)
f (c (Misc text) -> c (Misc text)) -> c (Misc text) -> c (Misc text)
forall a b. (a -> b) -> a -> b
$ d c tag text -> c (Misc text)
forall tag text. d c tag text -> c (Misc text)
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
d c tag text -> c (Misc text)
getTopLevelMiscs d c tag text
doc) (d c tag text -> NodeType d c tag text
forall tag text. d c tag text -> NodeType d c tag text
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
d c tag text -> NodeType d c tag text
getRoot d c tag text
doc)

modifyRoot :: DocumentClass d c =>
              (NodeType d c tag text -> NodeType d c tag text)
           -> d c tag text
           -> d c tag text
modifyRoot :: forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
(NodeType d c tag text -> NodeType d c tag text)
-> d c tag text -> d c tag text
modifyRoot NodeType d c tag text -> NodeType d c tag text
f d c tag text
doc = Maybe (XMLDeclaration text)
-> Maybe (DocumentTypeDeclaration c tag text)
-> c (Misc text)
-> NodeType d c tag text
-> d c tag text
forall text tag.
Maybe (XMLDeclaration text)
-> Maybe (DocumentTypeDeclaration c tag text)
-> c (Misc text)
-> NodeType d c tag text
-> d c tag text
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) text tag.
DocumentClass d c =>
Maybe (XMLDeclaration text)
-> Maybe (DocumentTypeDeclaration c tag text)
-> c (Misc text)
-> NodeType d c tag text
-> d c tag text
mkDocument (d c tag text -> Maybe (XMLDeclaration text)
forall tag text. d c tag text -> Maybe (XMLDeclaration text)
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
d c tag text -> Maybe (XMLDeclaration text)
getXMLDeclaration d c tag text
doc) (d c tag text -> Maybe (DocumentTypeDeclaration c tag text)
forall tag text.
d c tag text -> Maybe (DocumentTypeDeclaration c tag text)
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
d c tag text -> Maybe (DocumentTypeDeclaration c tag text)
getDocumentTypeDeclaration d c tag text
doc)
        (d c tag text -> c (Misc text)
forall tag text. d c tag text -> c (Misc text)
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
d c tag text -> c (Misc text)
getTopLevelMiscs d c tag text
doc) (NodeType d c tag text -> NodeType d c tag text
f (NodeType d c tag text -> NodeType d c tag text)
-> NodeType d c tag text -> NodeType d c tag text
forall a b. (a -> b) -> a -> b
$ d c tag text -> NodeType d c tag text
forall tag text. d c tag text -> NodeType d c tag text
forall (d :: (* -> *) -> * -> * -> *) (c :: * -> *) tag text.
DocumentClass d c =>
d c tag text -> NodeType d c tag text
getRoot d c tag text
doc)