    -- ------------------------------------------------------------

    {- |
       Module     : Text.XML.HXT.RelaxNG.BasicArrows
       Copyright  : Copyright (C) 2005 Uwe Schmidt
       License    : MIT

       Maintainer : Uwe Schmidt (uwe@fh-wedel.de)
       Stability  : experimental
       Portability: portable
       Version    : $Id$

       Constants and basic arrows for Relax NG

    -}

    -- ------------------------------------------------------------

    module Text.XML.HXT.RelaxNG.BasicArrows
    where

    import Control.Arrow.ListArrows

    import Text.XML.HXT.DOM.Interface
    import Text.XML.HXT.Arrow.XmlArrow
        hiding
        ( mkText
        , mkError
        )

    hasRngName      :: ArrowXml a => String -> a XmlTree XmlTree
    hasRngName s
        = hasName s
          `orElse`
          ( hasLocalPart s >>> hasNamespaceUri relaxNamespace )

    checkRngName :: ArrowXml a => [String] -> a XmlTree XmlTree
    checkRngName l
        = ( isElem
            >>>
            catA (map hasRngName l)
          )
          `guards` this

    noOfChildren    :: ArrowXml a => (Int -> Bool) -> a XmlTree XmlTree
    noOfChildren p
        = getChildren
          >>.
          (\ l -> if p (length l) then l else [])

    -- ------------------------------------------------------------

    isAttributeRef  :: ArrowXml a => a XmlTree XmlTree
    isAttributeRef
        = checkRngName ["attribute", "ref"]

    isAttributeRefTextListGroupInterleaveOneOrMoreEmpty     :: ArrowXml a => a XmlTree XmlTree
    isAttributeRefTextListGroupInterleaveOneOrMoreEmpty
        = checkRngName ["attribute", "ref", "text", "list", "group", "interleave", "oneOrMore", "empty"]

    isAttributeRefTextListInterleave        :: ArrowXml a => a XmlTree XmlTree
    isAttributeRefTextListInterleave
        = checkRngName ["attribute", "ref", "text", "list", "interleave"]

    isAttributeListGroupInterleaveOneOrMore :: ArrowXml a => a XmlTree XmlTree
    isAttributeListGroupInterleaveOneOrMore
        = checkRngName ["attribute", "list", "group", "interleave", "oneOrMore"]

    isExternalRefInclude    :: ArrowXml a => a XmlTree XmlTree
    isExternalRefInclude
        = checkRngName ["externalRef", "include"]

    isNameNsNameValue       :: ArrowXml a => a XmlTree XmlTree
    isNameNsNameValue
        = checkRngName ["name", "nsName", "value"]

    isNameNsName    :: ArrowXml a => a XmlTree XmlTree
    isNameNsName
        = checkRngName ["name", "nsName"]

    isNameAnyNameNsName     :: ArrowXml a => a XmlTree XmlTree
    isNameAnyNameNsName
        = checkRngName ["name", "anyName", "nsName"]

    isDefineOneOrMoreZeroOrMoreOptionalListMixed    :: ArrowXml a => a XmlTree XmlTree
    isDefineOneOrMoreZeroOrMoreOptionalListMixed
        = checkRngName ["define", "oneOrMore", "zeroOrMore", "optional", "list", "mixed"]

    isChoiceGroupInterleave :: ArrowXml a => a XmlTree XmlTree
    isChoiceGroupInterleave
        = checkRngName ["choice", "group", "interleave"]

    isChoiceGroupInterleaveOneOrMore        :: ArrowXml a => a XmlTree XmlTree
    isChoiceGroupInterleaveOneOrMore
        = checkRngName ["choice", "group", "interleave", "oneOrMore"]

    isGroupInterleave       :: ArrowXml a => a XmlTree XmlTree
    isGroupInterleave
        = checkRngName ["group", "interleave"]

    -- ------------------------------------------------------------

    isRngAnyName            :: ArrowXml a => a XmlTree XmlTree
    isRngAnyName            = isElem >>> hasRngName "anyName"

    isRngAttribute          :: ArrowXml a => a XmlTree XmlTree
    isRngAttribute          = isElem >>> hasRngName "attribute"

    isRngChoice             :: ArrowXml a => a XmlTree XmlTree
    isRngChoice             = isElem >>> hasRngName "choice"

    isRngCombine            :: ArrowXml a => a XmlTree XmlTree
    isRngCombine            = isElem >>> hasRngName "combine"

    isRngData               :: ArrowXml a => a XmlTree XmlTree
    isRngData               = isElem >>> hasRngName "data"

    isRngDefine             :: ArrowXml a => a XmlTree XmlTree
    isRngDefine             = isElem >>> hasRngName "define"

    isRngDiv                :: ArrowXml a => a XmlTree XmlTree
    isRngDiv                = isElem >>> hasRngName "div"

    isRngElement            :: ArrowXml a => a XmlTree XmlTree
    isRngElement            = isElem >>> hasRngName "element"

    isRngEmpty              :: ArrowXml a => a XmlTree XmlTree
    isRngEmpty              = isElem >>> hasRngName "empty"

    isRngExcept             :: ArrowXml a => a XmlTree XmlTree
    isRngExcept             = isElem >>> hasRngName "except"

    isRngExternalRef        :: ArrowXml a => a XmlTree XmlTree
    isRngExternalRef        = isElem >>> hasRngName "externalRef"

    isRngGrammar            :: ArrowXml a => a XmlTree XmlTree
    isRngGrammar            = isElem >>> hasRngName "grammar"

    isRngGroup              :: ArrowXml a => a XmlTree XmlTree
    isRngGroup              = isElem >>> hasRngName "group"

    isRngInclude            :: ArrowXml a => a XmlTree XmlTree
    isRngInclude            = isElem >>> hasRngName "include"

    isRngInterleave         :: ArrowXml a => a XmlTree XmlTree
    isRngInterleave         = isElem >>> hasRngName "interleave"

    isRngList               :: ArrowXml a => a XmlTree XmlTree
    isRngList               = isElem >>> hasRngName "list"

    isRngMixed              :: ArrowXml a => a XmlTree XmlTree
    isRngMixed              = isElem >>> hasRngName "mixed"

    isRngName               :: ArrowXml a => a XmlTree XmlTree
    isRngName               = isElem >>> hasRngName "name"

    isRngNotAllowed         :: ArrowXml a => a XmlTree XmlTree
    isRngNotAllowed         = isElem >>> hasRngName "notAllowed"

    isRngNsName             :: ArrowXml a => a XmlTree XmlTree
    isRngNsName             = isElem >>> hasRngName "nsName"

    isRngOneOrMore          :: ArrowXml a => a XmlTree XmlTree
    isRngOneOrMore          = isElem >>> hasRngName "oneOrMore"

    isRngOptional           :: ArrowXml a => a XmlTree XmlTree
    isRngOptional           = isElem >>> hasRngName "optional"

    isRngParam              :: ArrowXml a => a XmlTree XmlTree
    isRngParam              = isElem >>> hasRngName "param"

    isRngParentRef          :: ArrowXml a => a XmlTree XmlTree
    isRngParentRef          = isElem >>> hasRngName "parentRef"

    isRngRef                :: ArrowXml a => a XmlTree XmlTree
    isRngRef                = isElem >>> hasRngName "ref"

    isRngRelaxError         :: ArrowXml a => a XmlTree XmlTree
    isRngRelaxError         = isElem >>> hasRngName "relaxError"

    isRngStart              :: ArrowXml a => a XmlTree XmlTree
    isRngStart              = isElem >>> hasRngName "start"

    isRngText               :: ArrowXml a => a XmlTree XmlTree
    isRngText               = isElem >>> hasRngName "text"

    isRngType               :: ArrowXml a => a XmlTree XmlTree
    isRngType               = isElem >>> hasRngName "type"

    isRngValue              :: ArrowXml a => a XmlTree XmlTree
    isRngValue              = isElem >>> hasRngName "value"

    isRngZeroOrMore         :: ArrowXml a => a XmlTree XmlTree
    isRngZeroOrMore         = isElem >>> hasRngName "zeroOrMore"

    -- ------------------------------------------------------------

    mkRngElement            :: ArrowXml a => String -> a n XmlTree -> a n XmlTree -> a n XmlTree
    mkRngElement n          = mkElement (mkQName "" n relaxNamespace)

    mkRngChoice             :: ArrowXml a => a n XmlTree -> a n XmlTree -> a n XmlTree
    mkRngChoice             = mkRngElement "choice"

    mkRngDefine             :: ArrowXml a => a n XmlTree -> a n XmlTree -> a n XmlTree
    mkRngDefine             = mkRngElement "define"

    mkRngEmpty              :: ArrowXml a => a n XmlTree -> a n XmlTree
    mkRngEmpty a            = mkRngElement "empty" a none

    mkRngGrammar            :: ArrowXml a => a n XmlTree -> a n XmlTree -> a n XmlTree
    mkRngGrammar            = mkRngElement "grammar"

    mkRngGroup              :: ArrowXml a => a n XmlTree -> a n XmlTree -> a n XmlTree
    mkRngGroup              = mkRngElement "group"

    mkRngInterleave         :: ArrowXml a => a n XmlTree -> a n XmlTree -> a n XmlTree
    mkRngInterleave         = mkRngElement "interleave"

    mkRngName               :: ArrowXml a => a n XmlTree -> a n XmlTree -> a n XmlTree
    mkRngName               = mkRngElement "name"

    mkRngNotAllowed         :: ArrowXml a => a n XmlTree -> a n XmlTree -> a n XmlTree
    mkRngNotAllowed         = mkRngElement "notAllowed"

    mkRngOneOrMore          :: ArrowXml a => a n XmlTree -> a n XmlTree -> a n XmlTree
    mkRngOneOrMore          = mkRngElement "oneOrMore"

    mkRngRef                :: ArrowXml a => a n XmlTree -> a n XmlTree -> a n XmlTree
    mkRngRef                = mkRngElement "ref"

    mkRngRelaxError         :: ArrowXml a => a n XmlTree -> a n XmlTree -> a n XmlTree
    mkRngRelaxError         = mkRngElement "relaxError"

    mkRngStart              :: ArrowXml a => a n XmlTree -> a n XmlTree -> a n XmlTree
    mkRngStart              = mkRngElement "start"

    mkRngText               :: ArrowXml a => a n XmlTree -> a n XmlTree
    mkRngText a             = mkRngElement "text" a none

    -- ------------------------------------------------------------

    setRngName              :: ArrowXml a => String -> a XmlTree XmlTree
    setRngName n            = setElemName (mkQName "" n relaxNamespace)

    setRngNameDiv           :: ArrowXml a => a XmlTree XmlTree
    setRngNameDiv           = setRngName "div"

    setRngNameRef           :: ArrowXml a => a XmlTree XmlTree
    setRngNameRef           = setRngName "ref"

    -- ------------------------------------------------------------

    -- Attributes

    isRngAttrAttribute              :: ArrowXml a => a XmlTree XmlTree
    isRngAttrAttribute              = isAttr >>> hasRngName "attribute"

    isRngAttrCombine                :: ArrowXml a => a XmlTree XmlTree
    isRngAttrCombine                = isAttr >>> hasRngName "combine"

    isRngAttrDatatypeLibrary        :: ArrowXml a => a XmlTree XmlTree
    isRngAttrDatatypeLibrary        = isAttr >>> hasRngName "datatypeLibrary"

    isRngAttrHref                   :: ArrowXml a => a XmlTree XmlTree
    isRngAttrHref                   = isAttr >>> hasRngName "href"

    isRngAttrName                   :: ArrowXml a => a XmlTree XmlTree
    isRngAttrName                   = isAttr >>> hasRngName "name"

    isRngAttrNs                     :: ArrowXml a => a XmlTree XmlTree
    isRngAttrNs                     = isAttr >>> hasRngName "ns"

    isRngAttrType                   :: ArrowXml a => a XmlTree XmlTree
    isRngAttrType                   = isAttr >>> hasRngName "type"

    -- ------------------------------------------------------------

    hasRngAttrAttribute             :: ArrowXml a => a XmlTree XmlTree
    hasRngAttrAttribute             = hasAttr "attribute"

    hasRngAttrCombine               :: ArrowXml a => a XmlTree XmlTree
    hasRngAttrCombine               = hasAttr "combine"

    hasRngAttrDatatypeLibrary       :: ArrowXml a => a XmlTree XmlTree
    hasRngAttrDatatypeLibrary       = hasAttr "datatypeLibrary"

    hasRngAttrHref                  :: ArrowXml a => a XmlTree XmlTree
    hasRngAttrHref                  = hasAttr "href"

    hasRngAttrName                  :: ArrowXml a => a XmlTree XmlTree
    hasRngAttrName                  = hasAttr "name"

    hasRngAttrNs                    :: ArrowXml a => a XmlTree XmlTree
    hasRngAttrNs                    = hasAttr "ns"

    hasRngAttrType                  :: ArrowXml a => a XmlTree XmlTree
    hasRngAttrType                  = hasAttr "type"

    -- ------------------------------------------------------------

    getRngAttrAttribute             :: ArrowXml a => a XmlTree String
    getRngAttrAttribute             = getAttrValue "attribute"

    getRngAttrCombine               :: ArrowXml a => a XmlTree String
    getRngAttrCombine               = getAttrValue "combine"

    getRngAttrDatatypeLibrary       :: ArrowXml a => a XmlTree String
    getRngAttrDatatypeLibrary       = getAttrValue "datatypeLibrary"

    getRngAttrDescr                 :: ArrowXml a => a XmlTree String
    getRngAttrDescr                 = getAttrValue "descr"

    getRngAttrHref                  :: ArrowXml a => a XmlTree String
    getRngAttrHref                  = getAttrValue "href"

    getRngAttrName                  :: ArrowXml a => a XmlTree String
    getRngAttrName                  = getAttrValue "name"

    getRngAttrNs                    :: ArrowXml a => a XmlTree String
    getRngAttrNs                    = getAttrValue "ns"

    getRngAttrType                  :: ArrowXml a => a XmlTree String
    getRngAttrType                  = getAttrValue "type"

    -- ------------------------------------------------------------