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

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

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

   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

import Text.XML.HXT.RelaxNG.DataTypes
    ( a_relaxSimplificationChanges
    , defineOrigName
    , contextBaseAttr
    )

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

hasRngAttName           :: ArrowXml a => String -> a XmlTree XmlTree
hasRngAttName s
    = isAttr
      >>>
      hasLocalPart s
      >>>
      hasNamespaceUri ""

hasRngElemName          :: ArrowXml a => String -> a XmlTree XmlTree
hasRngElemName s
    = isElem
      >>>
      hasLocalPart s
      >>>
      hasNamespaceUri relaxNamespace

checkRngName :: ArrowXml a => [String] -> a XmlTree XmlTree
checkRngName l
    = catA (map hasRngElemName 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            = hasRngElemName "anyName"

isRngAttribute          :: ArrowXml a => a XmlTree XmlTree
isRngAttribute          = hasRngElemName "attribute"

isRngChoice             :: ArrowXml a => a XmlTree XmlTree
isRngChoice             = hasRngElemName "choice"

isRngCombine            :: ArrowXml a => a XmlTree XmlTree
isRngCombine            = hasRngElemName "combine"

isRngData               :: ArrowXml a => a XmlTree XmlTree
isRngData               = hasRngElemName "data"

isRngDefine             :: ArrowXml a => a XmlTree XmlTree
isRngDefine             = hasRngElemName "define"

isRngDiv                :: ArrowXml a => a XmlTree XmlTree
isRngDiv                = hasRngElemName "div"

isRngElement            :: ArrowXml a => a XmlTree XmlTree
isRngElement            = hasRngElemName "element"

isRngEmpty              :: ArrowXml a => a XmlTree XmlTree
isRngEmpty              = hasRngElemName "empty"

isRngExcept             :: ArrowXml a => a XmlTree XmlTree
isRngExcept             = hasRngElemName "except"

isRngExternalRef        :: ArrowXml a => a XmlTree XmlTree
isRngExternalRef        = hasRngElemName "externalRef"

isRngGrammar            :: ArrowXml a => a XmlTree XmlTree
isRngGrammar            = hasRngElemName "grammar"

isRngGroup              :: ArrowXml a => a XmlTree XmlTree
isRngGroup              = hasRngElemName "group"

isRngInclude            :: ArrowXml a => a XmlTree XmlTree
isRngInclude            = hasRngElemName "include"

isRngInterleave         :: ArrowXml a => a XmlTree XmlTree
isRngInterleave         = hasRngElemName "interleave"

isRngList               :: ArrowXml a => a XmlTree XmlTree
isRngList               = hasRngElemName "list"

isRngMixed              :: ArrowXml a => a XmlTree XmlTree
isRngMixed              = hasRngElemName "mixed"

isRngName               :: ArrowXml a => a XmlTree XmlTree
isRngName               = hasRngElemName "name"

isRngNotAllowed         :: ArrowXml a => a XmlTree XmlTree
isRngNotAllowed         = hasRngElemName "notAllowed"

isRngNsName             :: ArrowXml a => a XmlTree XmlTree
isRngNsName             = hasRngElemName "nsName"

isRngOneOrMore          :: ArrowXml a => a XmlTree XmlTree
isRngOneOrMore          = hasRngElemName "oneOrMore"

isRngOptional           :: ArrowXml a => a XmlTree XmlTree
isRngOptional           = hasRngElemName "optional"

isRngParam              :: ArrowXml a => a XmlTree XmlTree
isRngParam              = hasRngElemName "param"

isRngParentRef          :: ArrowXml a => a XmlTree XmlTree
isRngParentRef          = hasRngElemName "parentRef"

isRngRef                :: ArrowXml a => a XmlTree XmlTree
isRngRef                = hasRngElemName "ref"

isRngRelaxError         :: ArrowXml a => a XmlTree XmlTree
isRngRelaxError         = hasRngElemName "relaxError"

isRngStart              :: ArrowXml a => a XmlTree XmlTree
isRngStart              = hasRngElemName "start"

isRngText               :: ArrowXml a => a XmlTree XmlTree
isRngText               = hasRngElemName "text"

isRngType               :: ArrowXml a => a XmlTree XmlTree
isRngType               = hasRngElemName "type"

isRngValue              :: ArrowXml a => a XmlTree XmlTree
isRngValue              = hasRngElemName "value"

isRngZeroOrMore         :: ArrowXml a => a XmlTree XmlTree
isRngZeroOrMore         = hasRngElemName "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
mkRngRelaxError         = mkRngElement "relaxError" none none

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              = hasRngAttName "attribute"

isRngAttrCombine                :: ArrowXml a => a XmlTree XmlTree
isRngAttrCombine                = hasRngAttName "combine"

isRngAttrDatatypeLibrary        :: ArrowXml a => a XmlTree XmlTree
isRngAttrDatatypeLibrary        = hasRngAttName "datatypeLibrary"

isRngAttrHref                   :: ArrowXml a => a XmlTree XmlTree
isRngAttrHref                   = hasRngAttName "href"

isRngAttrName                   :: ArrowXml a => a XmlTree XmlTree
isRngAttrName                   = hasRngAttName "name"

isRngAttrNs                     :: ArrowXml a => a XmlTree XmlTree
isRngAttrNs                     = hasRngAttName "ns"

isRngAttrType                   :: ArrowXml a => a XmlTree XmlTree
isRngAttrType                   = hasRngAttName "type"

isRngAttrRelaxSimplificationChanges     :: ArrowXml a => a XmlTree XmlTree
isRngAttrRelaxSimplificationChanges     = hasRngAttName a_relaxSimplificationChanges

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

mkRngAttr                       :: ArrowXml a => String -> a b String -> a b XmlTree
mkRngAttr name value            = mkAttr (mkName name) (value >>> mkText)

mkRngAttrName                   :: ArrowXml a => String -> a b XmlTree
mkRngAttrName value             = mkRngAttr "name" (constA value)

mkRngAttrRelaxSimplificationChanges     :: ArrowXml a => String -> a b XmlTree
mkRngAttrRelaxSimplificationChanges value
                                = mkRngAttr a_relaxSimplificationChanges (constA value)

mkRngAttrDefineOrigName         :: ArrowXml a => String -> a b XmlTree
mkRngAttrDefineOrigName value   = mkRngAttr defineOrigName (constA value)

mkRngAttrContextBase            :: ArrowXml a => a b String -> a b XmlTree
mkRngAttrContextBase            = mkRngAttr contextBaseAttr

addRngAttrName                  :: ArrowXml a => String -> a XmlTree XmlTree
addRngAttrName value            = addAttr "name" value

addRngAttrDescr                 :: ArrowXml a => String -> a XmlTree XmlTree
addRngAttrDescr                 = addAttr "descr"

addRngAttrChanges               :: ArrowXml a => String -> a XmlTree XmlTree
addRngAttrChanges               = addAttr "changes"

addRngAttrNs                    :: ArrowXml a => String -> a XmlTree XmlTree
addRngAttrNs                    = addAttr "ns"

rmRngAttrNs                     :: ArrowXml a => a XmlTree XmlTree
rmRngAttrNs                     = removeAttr "ns"

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

hasRngAttrRelaxSimplificationChanges             :: ArrowXml a => a XmlTree XmlTree
hasRngAttrRelaxSimplificationChanges             = hasAttr a_relaxSimplificationChanges

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"

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