    {-# LANGUAGE CPP #-}
    {-# LANGUAGE DeriveGeneric #-}
    {-# LANGUAGE MultiParamTypeClasses #-}
    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE RecordWildCards #-}
    {-# LANGUAGE TemplateHaskell #-}
    module Codec.Xlsx.Types.DataValidation
      ( ValidationExpression(..)
        , ValidationType(..)
        , dvAllowBlank
        , dvError
        , dvErrorStyle
        , dvErrorTitle
        , dvPrompt
        , dvPromptTitle
        , dvShowDropDown
        , dvShowErrorMessage
        , dvShowInputMessage
        , dvValidationType
        , ErrorStyle(..)
        , DataValidation(..)
        , ListOrRangeExpression(..)
        , ValidationList
        , maybePlainValidationList
        , maybeValidationRange
        , readValidationType
        , readListFormulas
        , readOpExpression2
        , readValidationTypeOpExp
        , readValExpression
        , viewValidationExpression
      ) where

    import Control.Applicative ((<|>))
    import Control.DeepSeq (NFData)
    #ifdef USE_MICROLENS
    import Lens.Micro.TH (makeLenses)
    #else
    import Control.Lens.TH (makeLenses)
    #endif
    import Control.Monad ((>=>), guard)
    import Data.ByteString (ByteString)
    import Data.Char (isSpace)
    import Data.Default
    import qualified Data.Map as M
    import Data.Maybe (catMaybes, maybeToList)
    import Data.Monoid ((<>))
    import Data.Text (Text)
    import qualified Data.Text as T
    import GHC.Generics (Generic)
    import Text.XML (Element(..), Node(..))
    import Text.XML.Cursor (Cursor, ($/), element)

    import Codec.Xlsx.Parser.Internal
    import Codec.Xlsx.Types.Common
    import Codec.Xlsx.Writer.Internal

    -- See 18.18.20 "ST_DataValidationOperator (Data Validation Operator)" (p. 2439/2449)
    data ValidationExpression
        = ValBetween Formula Formula    -- ^ "Between" operator
        | ValEqual Formula              -- ^ "Equal to" operator
        | ValGreaterThan Formula        -- ^ "Greater than" operator
        | ValGreaterThanOrEqual Formula -- ^ "Greater than or equal to" operator
        | ValLessThan Formula           -- ^ "Less than" operator
        | ValLessThanOrEqual Formula    -- ^ "Less than or equal to" operator
        | ValNotBetween Formula Formula -- ^ "Not between" operator
        | ValNotEqual Formula           -- ^ "Not equal to" operator
        deriving (ValidationExpression -> ValidationExpression -> Bool
    (ValidationExpression -> ValidationExpression -> Bool)
    -> (ValidationExpression -> ValidationExpression -> Bool)
    -> Eq ValidationExpression
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ValidationExpression -> ValidationExpression -> Bool
    == :: ValidationExpression -> ValidationExpression -> Bool
    $c/= :: ValidationExpression -> ValidationExpression -> Bool
    /= :: ValidationExpression -> ValidationExpression -> Bool
    Eq, Int -> ValidationExpression -> ShowS
    [ValidationExpression] -> ShowS
    ValidationExpression -> String
    (Int -> ValidationExpression -> ShowS)
    -> (ValidationExpression -> String)
    -> ([ValidationExpression] -> ShowS)
    -> Show ValidationExpression
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ValidationExpression -> ShowS
    showsPrec :: Int -> ValidationExpression -> ShowS
    $cshow :: ValidationExpression -> String
    show :: ValidationExpression -> String
    $cshowList :: [ValidationExpression] -> ShowS
    showList :: [ValidationExpression] -> ShowS
    Show, (forall x. ValidationExpression -> Rep ValidationExpression x)
    -> (forall x. Rep ValidationExpression x -> ValidationExpression)
    -> Generic ValidationExpression
    forall x. Rep ValidationExpression x -> ValidationExpression
    forall x. ValidationExpression -> Rep ValidationExpression x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. ValidationExpression -> Rep ValidationExpression x
    from :: forall x. ValidationExpression -> Rep ValidationExpression x
    $cto :: forall x. Rep ValidationExpression x -> ValidationExpression
    to :: forall x. Rep ValidationExpression x -> ValidationExpression
    Generic)
    instance NFData ValidationExpression

    -- See 18.18.21 "ST_DataValidationType (Data Validation Type)" (p. 2440/2450)
    data ValidationType
        = ValidationTypeNone
        | ValidationTypeCustom     Formula
        | ValidationTypeDate       ValidationExpression
        | ValidationTypeDecimal    ValidationExpression
        | ValidationTypeList       ListOrRangeExpression
        | ValidationTypeTextLength ValidationExpression
        | ValidationTypeTime       ValidationExpression
        | ValidationTypeWhole      ValidationExpression
        deriving (ValidationType -> ValidationType -> Bool
    (ValidationType -> ValidationType -> Bool)
    -> (ValidationType -> ValidationType -> Bool) -> Eq ValidationType
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ValidationType -> ValidationType -> Bool
    == :: ValidationType -> ValidationType -> Bool
    $c/= :: ValidationType -> ValidationType -> Bool
    /= :: ValidationType -> ValidationType -> Bool
    Eq, Int -> ValidationType -> ShowS
    [ValidationType] -> ShowS
    ValidationType -> String
    (Int -> ValidationType -> ShowS)
    -> (ValidationType -> String)
    -> ([ValidationType] -> ShowS)
    -> Show ValidationType
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ValidationType -> ShowS
    showsPrec :: Int -> ValidationType -> ShowS
    $cshow :: ValidationType -> String
    show :: ValidationType -> String
    $cshowList :: [ValidationType] -> ShowS
    showList :: [ValidationType] -> ShowS
    Show, (forall x. ValidationType -> Rep ValidationType x)
    -> (forall x. Rep ValidationType x -> ValidationType)
    -> Generic ValidationType
    forall x. Rep ValidationType x -> ValidationType
    forall x. ValidationType -> Rep ValidationType x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. ValidationType -> Rep ValidationType x
    from :: forall x. ValidationType -> Rep ValidationType x
    $cto :: forall x. Rep ValidationType x -> ValidationType
    to :: forall x. Rep ValidationType x -> ValidationType
    Generic)
    instance NFData ValidationType

    type ValidationList = [Text]

    data ListOrRangeExpression
      = ListExpression ValidationList -- ^ a plain list of elements
      | RangeExpression Range -- ^ a cell or range reference
      deriving (ListOrRangeExpression -> ListOrRangeExpression -> Bool
    (ListOrRangeExpression -> ListOrRangeExpression -> Bool)
    -> (ListOrRangeExpression -> ListOrRangeExpression -> Bool)
    -> Eq ListOrRangeExpression
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ListOrRangeExpression -> ListOrRangeExpression -> Bool
    == :: ListOrRangeExpression -> ListOrRangeExpression -> Bool
    $c/= :: ListOrRangeExpression -> ListOrRangeExpression -> Bool
    /= :: ListOrRangeExpression -> ListOrRangeExpression -> Bool
    Eq, Int -> ListOrRangeExpression -> ShowS
    [ListOrRangeExpression] -> ShowS
    ListOrRangeExpression -> String
    (Int -> ListOrRangeExpression -> ShowS)
    -> (ListOrRangeExpression -> String)
    -> ([ListOrRangeExpression] -> ShowS)
    -> Show ListOrRangeExpression
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ListOrRangeExpression -> ShowS
    showsPrec :: Int -> ListOrRangeExpression -> ShowS
    $cshow :: ListOrRangeExpression -> String
    show :: ListOrRangeExpression -> String
    $cshowList :: [ListOrRangeExpression] -> ShowS
    showList :: [ListOrRangeExpression] -> ShowS
    Show, (forall x. ListOrRangeExpression -> Rep ListOrRangeExpression x)
    -> (forall x. Rep ListOrRangeExpression x -> ListOrRangeExpression)
    -> Generic ListOrRangeExpression
    forall x. Rep ListOrRangeExpression x -> ListOrRangeExpression
    forall x. ListOrRangeExpression -> Rep ListOrRangeExpression x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. ListOrRangeExpression -> Rep ListOrRangeExpression x
    from :: forall x. ListOrRangeExpression -> Rep ListOrRangeExpression x
    $cto :: forall x. Rep ListOrRangeExpression x -> ListOrRangeExpression
    to :: forall x. Rep ListOrRangeExpression x -> ListOrRangeExpression
    Generic)
    instance NFData ListOrRangeExpression

    -- See 18.18.18 "ST_DataValidationErrorStyle (Data Validation Error Styles)" (p. 2438/2448)
    data ErrorStyle
        = ErrorStyleInformation
        | ErrorStyleStop
        | ErrorStyleWarning
        deriving (ErrorStyle -> ErrorStyle -> Bool
    (ErrorStyle -> ErrorStyle -> Bool)
    -> (ErrorStyle -> ErrorStyle -> Bool) -> Eq ErrorStyle
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ErrorStyle -> ErrorStyle -> Bool
    == :: ErrorStyle -> ErrorStyle -> Bool
    $c/= :: ErrorStyle -> ErrorStyle -> Bool
    /= :: ErrorStyle -> ErrorStyle -> Bool
    Eq, Int -> ErrorStyle -> ShowS
    [ErrorStyle] -> ShowS
    ErrorStyle -> String
    (Int -> ErrorStyle -> ShowS)
    -> (ErrorStyle -> String)
    -> ([ErrorStyle] -> ShowS)
    -> Show ErrorStyle
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ErrorStyle -> ShowS
    showsPrec :: Int -> ErrorStyle -> ShowS
    $cshow :: ErrorStyle -> String
    show :: ErrorStyle -> String
    $cshowList :: [ErrorStyle] -> ShowS
    showList :: [ErrorStyle] -> ShowS
    Show, (forall x. ErrorStyle -> Rep ErrorStyle x)
    -> (forall x. Rep ErrorStyle x -> ErrorStyle) -> Generic ErrorStyle
    forall x. Rep ErrorStyle x -> ErrorStyle
    forall x. ErrorStyle -> Rep ErrorStyle x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. ErrorStyle -> Rep ErrorStyle x
    from :: forall x. ErrorStyle -> Rep ErrorStyle x
    $cto :: forall x. Rep ErrorStyle x -> ErrorStyle
    to :: forall x. Rep ErrorStyle x -> ErrorStyle
    Generic)
    instance NFData ErrorStyle

    -- See 18.3.1.32 "dataValidation (Data Validation)" (p. 1614/1624)
    data DataValidation = DataValidation
        { DataValidation -> Bool
    _dvAllowBlank       :: Bool
        , DataValidation -> Maybe Text
    _dvError            :: Maybe Text
        , DataValidation -> ErrorStyle
    _dvErrorStyle       :: ErrorStyle
        , DataValidation -> Maybe Text
    _dvErrorTitle       :: Maybe Text
        , DataValidation -> Maybe Text
    _dvPrompt           :: Maybe Text
        , DataValidation -> Maybe Text
    _dvPromptTitle      :: Maybe Text
        , DataValidation -> Bool
    _dvShowDropDown     :: Bool
        , DataValidation -> Bool
    _dvShowErrorMessage :: Bool
        , DataValidation -> Bool
    _dvShowInputMessage :: Bool
        , DataValidation -> ValidationType
    _dvValidationType   :: ValidationType
        } deriving (DataValidation -> DataValidation -> Bool
    (DataValidation -> DataValidation -> Bool)
    -> (DataValidation -> DataValidation -> Bool) -> Eq DataValidation
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: DataValidation -> DataValidation -> Bool
    == :: DataValidation -> DataValidation -> Bool
    $c/= :: DataValidation -> DataValidation -> Bool
    /= :: DataValidation -> DataValidation -> Bool
    Eq, Int -> DataValidation -> ShowS
    [DataValidation] -> ShowS
    DataValidation -> String
    (Int -> DataValidation -> ShowS)
    -> (DataValidation -> String)
    -> ([DataValidation] -> ShowS)
    -> Show DataValidation
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> DataValidation -> ShowS
    showsPrec :: Int -> DataValidation -> ShowS
    $cshow :: DataValidation -> String
    show :: DataValidation -> String
    $cshowList :: [DataValidation] -> ShowS
    showList :: [DataValidation] -> ShowS
    Show, (forall x. DataValidation -> Rep DataValidation x)
    -> (forall x. Rep DataValidation x -> DataValidation)
    -> Generic DataValidation
    forall x. Rep DataValidation x -> DataValidation
    forall x. DataValidation -> Rep DataValidation x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. DataValidation -> Rep DataValidation x
    from :: forall x. DataValidation -> Rep DataValidation x
    $cto :: forall x. Rep DataValidation x -> DataValidation
    to :: forall x. Rep DataValidation x -> DataValidation
    Generic)
    instance NFData DataValidation

    makeLenses ''DataValidation

    instance Default DataValidation where
        def :: DataValidation
    def = Bool
    -> Maybe Text
    -> ErrorStyle
    -> Maybe Text
    -> Maybe Text
    -> Maybe Text
    -> Bool
    -> Bool
    -> Bool
    -> ValidationType
    -> DataValidation
    DataValidation
          Bool
    False Maybe Text
    forall a. Maybe a
    Nothing ErrorStyle
    ErrorStyleStop Maybe Text
    forall a. Maybe a
    Nothing Maybe Text
    forall a. Maybe a
    Nothing Maybe Text
    forall a. Maybe a
    Nothing Bool
    False Bool
    False Bool
    False ValidationType
    ValidationTypeNone

    {-------------------------------------------------------------------------------
      Parsing
    -------------------------------------------------------------------------------}

    instance FromAttrVal ErrorStyle where
        fromAttrVal :: Reader ErrorStyle
    fromAttrVal Text
    "information" = ErrorStyle -> Either String (ErrorStyle, Text)
    forall a. a -> Either String (a, Text)
    readSuccess ErrorStyle
    ErrorStyleInformation
        fromAttrVal Text
    "stop"        = ErrorStyle -> Either String (ErrorStyle, Text)
    forall a. a -> Either String (a, Text)
    readSuccess ErrorStyle
    ErrorStyleStop
        fromAttrVal Text
    "warning"     = ErrorStyle -> Either String (ErrorStyle, Text)
    forall a. a -> Either String (a, Text)
    readSuccess ErrorStyle
    ErrorStyleWarning
        fromAttrVal Text
    t             = Text -> Reader ErrorStyle
    forall a. Text -> Text -> Either String (a, Text)
    invalidText Text
    "ErrorStyle" Text
    t

    instance FromAttrBs ErrorStyle where
        fromAttrBs :: ByteString -> Either Text ErrorStyle
    fromAttrBs ByteString
    "information" = ErrorStyle -> Either Text ErrorStyle
    forall a. a -> Either Text a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ErrorStyle
    ErrorStyleInformation
        fromAttrBs ByteString
    "stop"        = ErrorStyle -> Either Text ErrorStyle
    forall a. a -> Either Text a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ErrorStyle
    ErrorStyleStop
        fromAttrBs ByteString
    "warning"     = ErrorStyle -> Either Text ErrorStyle
    forall a. a -> Either Text a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ErrorStyle
    ErrorStyleWarning
        fromAttrBs ByteString
    x             = Text -> ByteString -> Either Text ErrorStyle
    forall a. Text -> ByteString -> Either Text a
    unexpectedAttrBs Text
    "ErrorStyle" ByteString
    x

    instance FromCursor DataValidation where
        fromCursor :: Cursor -> [DataValidation]
    fromCursor Cursor
    cur = do
            _dvAllowBlank       <- Name -> Bool -> Cursor -> [Bool]
    forall a. FromAttrVal a => Name -> a -> Cursor -> [a]
    fromAttributeDef Name
    "allowBlank"       Bool
    False          Cursor
    cur
            _dvError            <- maybeAttribute   "error"                           cur
            _dvErrorStyle       <- fromAttributeDef "errorStyle"       ErrorStyleStop cur
            _dvErrorTitle       <- maybeAttribute   "errorTitle"                      cur
            mop                 <- fromAttributeDef "operator"         "between"      cur
            _dvPrompt           <- maybeAttribute   "prompt"                          cur
            _dvPromptTitle      <- maybeAttribute   "promptTitle"                     cur
            _dvShowDropDown     <- fromAttributeDef "showDropDown"     False          cur
            _dvShowErrorMessage <- fromAttributeDef "showErrorMessage" False          cur
            _dvShowInputMessage <- fromAttributeDef "showInputMessage" False          cur
            mtype               <- fromAttributeDef "type"             "none"         cur
            _dvValidationType   <- readValidationType mop mtype                       cur
            return DataValidation{..}

    instance FromXenoNode DataValidation where
      fromXenoNode :: Node -> Either Text DataValidation
    fromXenoNode Node
    root = do
        (op, atype, genDV) <- Node
    -> AttrParser
         (ByteString, ByteString, ValidationType -> DataValidation)
    -> Either
         Text (ByteString, ByteString, ValidationType -> DataValidation)
    forall a. Node -> AttrParser a -> Either Text a
    parseAttributes Node
    root (AttrParser
       (ByteString, ByteString, ValidationType -> DataValidation)
     -> Either
          Text (ByteString, ByteString, ValidationType -> DataValidation))
    -> AttrParser
         (ByteString, ByteString, ValidationType -> DataValidation)
    -> Either
         Text (ByteString, ByteString, ValidationType -> DataValidation)
    forall a b. (a -> b) -> a -> b
    $ do
          _dvAllowBlank <- ByteString -> Bool -> AttrParser Bool
    forall a. FromAttrBs a => ByteString -> a -> AttrParser a
    fromAttrDef ByteString
    "allowBlank" Bool
    False
          _dvError <- maybeAttr "error"
          _dvErrorStyle <- fromAttrDef "errorStyle" ErrorStyleStop
          _dvErrorTitle <- maybeAttr "errorTitle"
          _dvPrompt <- maybeAttr "prompt"
          _dvPromptTitle <- maybeAttr "promptTitle"
          _dvShowDropDown <- fromAttrDef "showDropDown" False
          _dvShowErrorMessage <- fromAttrDef "showErrorMessage" False
          _dvShowInputMessage <- fromAttrDef "showInputMessage" False
          op <- fromAttrDef "operator" "between"
          typ <- fromAttrDef "type" "none"
          return (op, typ, \ValidationType
    _dvValidationType -> DataValidation {Bool
    Maybe Text
    ErrorStyle
    ValidationType
    _dvAllowBlank :: Bool
    _dvError :: Maybe Text
    _dvErrorStyle :: ErrorStyle
    _dvErrorTitle :: Maybe Text
    _dvPrompt :: Maybe Text
    _dvPromptTitle :: Maybe Text
    _dvShowDropDown :: Bool
    _dvShowErrorMessage :: Bool
    _dvShowInputMessage :: Bool
    _dvValidationType :: ValidationType
    _dvAllowBlank :: Bool
    _dvError :: Maybe Text
    _dvErrorStyle :: ErrorStyle
    _dvErrorTitle :: Maybe Text
    _dvPrompt :: Maybe Text
    _dvPromptTitle :: Maybe Text
    _dvShowDropDown :: Bool
    _dvShowErrorMessage :: Bool
    _dvShowInputMessage :: Bool
    _dvValidationType :: ValidationType
    ..})
        valType <- parseValidationType op atype
        return $ genDV valType
        where
          parseValidationType :: ByteString -> ByteString -> Either Text ValidationType
          parseValidationType :: ByteString -> ByteString -> Either Text ValidationType
    parseValidationType ByteString
    op ByteString
    atype =
            case ByteString
    atype of
              ByteString
    "none" -> ValidationType -> Either Text ValidationType
    forall a. a -> Either Text a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ValidationType
    ValidationTypeNone
              ByteString
    "custom" ->
                Formula -> ValidationType
    ValidationTypeCustom (Formula -> ValidationType)
    -> Either Text Formula -> Either Text ValidationType
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Either Text Formula
    formula1
              ByteString
    "list" -> do
                f <- Either Text Formula
    formula1
                case readListFormulas f of
                  Maybe ListOrRangeExpression
    Nothing -> Text -> Either Text ValidationType
    forall a b. a -> Either a b
    Left Text
    "validation of type \"list\" with empty formula list"
                  Just ListOrRangeExpression
    fs -> ValidationType -> Either Text ValidationType
    forall a. a -> Either Text a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (ValidationType -> Either Text ValidationType)
    -> ValidationType -> Either Text ValidationType
    forall a b. (a -> b) -> a -> b
    $ ListOrRangeExpression -> ValidationType
    ValidationTypeList ListOrRangeExpression
    fs
              ByteString
    "date" ->
                ValidationExpression -> ValidationType
    ValidationTypeDate (ValidationExpression -> ValidationType)
    -> Either Text ValidationExpression -> Either Text ValidationType
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> ByteString -> Either Text ValidationExpression
    forall {a}.
    (Eq a, IsString a, Show a) =>
    a -> Either Text ValidationExpression
    readOpExpression ByteString
    op
              ByteString
    "decimal"    ->
                ValidationExpression -> ValidationType
    ValidationTypeDecimal (ValidationExpression -> ValidationType)
    -> Either Text ValidationExpression -> Either Text ValidationType
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> ByteString -> Either Text ValidationExpression
    forall {a}.
    (Eq a, IsString a, Show a) =>
    a -> Either Text ValidationExpression
    readOpExpression ByteString
    op
              ByteString
    "textLength" ->
                ValidationExpression -> ValidationType
    ValidationTypeTextLength (ValidationExpression -> ValidationType)
    -> Either Text ValidationExpression -> Either Text ValidationType
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> ByteString -> Either Text ValidationExpression
    forall {a}.
    (Eq a, IsString a, Show a) =>
    a -> Either Text ValidationExpression
    readOpExpression ByteString
    op
              ByteString
    "time"       ->
                ValidationExpression -> ValidationType
    ValidationTypeTime (ValidationExpression -> ValidationType)
    -> Either Text ValidationExpression -> Either Text ValidationType
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> ByteString -> Either Text ValidationExpression
    forall {a}.
    (Eq a, IsString a, Show a) =>
    a -> Either Text ValidationExpression
    readOpExpression ByteString
    op
              ByteString
    "whole"      ->
                ValidationExpression -> ValidationType
    ValidationTypeWhole (ValidationExpression -> ValidationType)
    -> Either Text ValidationExpression -> Either Text ValidationType
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> ByteString -> Either Text ValidationExpression
    forall {a}.
    (Eq a, IsString a, Show a) =>
    a -> Either Text ValidationExpression
    readOpExpression ByteString
    op
              ByteString
    unexpected ->
                Text -> Either Text ValidationType
    forall a b. a -> Either a b
    Left (Text -> Either Text ValidationType)
    -> Text -> Either Text ValidationType
    forall a b. (a -> b) -> a -> b
    $ Text
    "unexpected type of data validation " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> String -> Text
    T.pack (ByteString -> String
    forall a. Show a => a -> String
    show ByteString
    unexpected)
          readOpExpression :: a -> Either Text ValidationExpression
    readOpExpression a
    "between" = (Formula -> Formula -> ValidationExpression)
    -> (Formula, Formula) -> ValidationExpression
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry Formula -> Formula -> ValidationExpression
    ValBetween ((Formula, Formula) -> ValidationExpression)
    -> Either Text (Formula, Formula)
    -> Either Text ValidationExpression
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Either Text (Formula, Formula)
    formulaPair
          readOpExpression a
    "notBetween" = (Formula -> Formula -> ValidationExpression)
    -> (Formula, Formula) -> ValidationExpression
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry Formula -> Formula -> ValidationExpression
    ValNotBetween ((Formula, Formula) -> ValidationExpression)
    -> Either Text (Formula, Formula)
    -> Either Text ValidationExpression
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Either Text (Formula, Formula)
    formulaPair
          readOpExpression a
    "equal" = Formula -> ValidationExpression
    ValEqual (Formula -> ValidationExpression)
    -> Either Text Formula -> Either Text ValidationExpression
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Either Text Formula
    formula1
          readOpExpression a
    "greaterThan" = Formula -> ValidationExpression
    ValGreaterThan (Formula -> ValidationExpression)
    -> Either Text Formula -> Either Text ValidationExpression
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Either Text Formula
    formula1
          readOpExpression a
    "greaterThanOrEqual" = Formula -> ValidationExpression
    ValGreaterThanOrEqual (Formula -> ValidationExpression)
    -> Either Text Formula -> Either Text ValidationExpression
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Either Text Formula
    formula1
          readOpExpression a
    "lessThan" = Formula -> ValidationExpression
    ValLessThan (Formula -> ValidationExpression)
    -> Either Text Formula -> Either Text ValidationExpression
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Either Text Formula
    formula1
          readOpExpression a
    "lessThanOrEqual" = Formula -> ValidationExpression
    ValLessThanOrEqual (Formula -> ValidationExpression)
    -> Either Text Formula -> Either Text ValidationExpression
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Either Text Formula
    formula1
          readOpExpression a
    "notEqual" = Formula -> ValidationExpression
    ValNotEqual (Formula -> ValidationExpression)
    -> Either Text Formula -> Either Text ValidationExpression
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Either Text Formula
    formula1
          readOpExpression a
    op = Text -> Either Text ValidationExpression
    forall a b. a -> Either a b
    Left (Text -> Either Text ValidationExpression)
    -> Text -> Either Text ValidationExpression
    forall a b. (a -> b) -> a -> b
    $ Text
    "data validation, unexpected operator " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> String -> Text
    T.pack (a -> String
    forall a. Show a => a -> String
    show a
    op)
          formula1 :: Either Text Formula
    formula1 = Node -> ChildCollector Formula -> Either Text Formula
    forall a. Node -> ChildCollector a -> Either Text a
    collectChildren Node
    root (ChildCollector Formula -> Either Text Formula)
    -> ChildCollector Formula -> Either Text Formula
    forall a b. (a -> b) -> a -> b
    $ ByteString -> ChildCollector Formula
    forall a. FromXenoNode a => ByteString -> ChildCollector a
    fromChild ByteString
    "formula1"
          formulaPair :: Either Text (Formula, Formula)
    formulaPair =
            Node
    -> ChildCollector (Formula, Formula)
    -> Either Text (Formula, Formula)
    forall a. Node -> ChildCollector a -> Either Text a
    collectChildren Node
    root (ChildCollector (Formula, Formula)
     -> Either Text (Formula, Formula))
    -> ChildCollector (Formula, Formula)
    -> Either Text (Formula, Formula)
    forall a b. (a -> b) -> a -> b
    $ (,) (Formula -> Formula -> (Formula, Formula))
    -> ChildCollector Formula
    -> ChildCollector (Formula -> (Formula, Formula))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> ByteString -> ChildCollector Formula
    forall a. FromXenoNode a => ByteString -> ChildCollector a
    fromChild ByteString
    "formula1" ChildCollector (Formula -> (Formula, Formula))
    -> ChildCollector Formula -> ChildCollector (Formula, Formula)
    forall a b.
    ChildCollector (a -> b) -> ChildCollector a -> ChildCollector b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> ByteString -> ChildCollector Formula
    forall a. FromXenoNode a => ByteString -> ChildCollector a
    fromChild ByteString
    "formula2"

    readValidationType :: Text -> Text -> Cursor -> [ValidationType]
    readValidationType :: Text -> Text -> Cursor -> [ValidationType]
    readValidationType Text
    _ Text
    "none"   Cursor
    _   = ValidationType -> [ValidationType]
    forall a. a -> [a]
    forall (m :: * -> *) a. Monad m => a -> m a
    return ValidationType
    ValidationTypeNone
    readValidationType Text
    _ Text
    "custom" Cursor
    cur = do
        f <- Cursor -> [Formula]
    forall a. FromCursor a => Cursor -> [a]
    fromCursor Cursor
    cur
        return $ ValidationTypeCustom f
    readValidationType Text
    _ Text
    "list" Cursor
    cur = do
        f  <- Cursor
    cur Cursor -> (Cursor -> [Formula]) -> [Formula]
    forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
    $/ Name -> Axis
    element (Text -> Name
    n_ Text
    "formula1") Axis -> (Cursor -> [Formula]) -> Cursor -> [Formula]
    forall (m :: * -> *) a b c.
    Monad m =>
    (a -> m b) -> (b -> m c) -> a -> m c
    >=> Cursor -> [Formula]
    forall a. FromCursor a => Cursor -> [a]
    fromCursor
        as <- maybeToList $ readListFormulas f
        return $ ValidationTypeList as
    readValidationType Text
    op Text
    ty Cursor
    cur = do
        opExp <- Text -> Cursor -> [ValidationExpression]
    readOpExpression2 Text
    op Cursor
    cur
        readValidationTypeOpExp ty opExp

    -- | Attempt to obtain a plain list expression
    maybePlainValidationList :: ValidationType -> Maybe ValidationList
    maybePlainValidationList :: ValidationType -> Maybe ValidationList
    maybePlainValidationList (ValidationTypeList (ListExpression ValidationList
    le)) = ValidationList -> Maybe ValidationList
    forall a. a -> Maybe a
    Just ValidationList
    le
    maybePlainValidationList ValidationType
    _ = Maybe ValidationList
    forall a. Maybe a
    Nothing

    -- | Attempt to obtain a range expression
    maybeValidationRange :: ValidationType -> Maybe Range
    maybeValidationRange :: ValidationType -> Maybe Range
    maybeValidationRange (ValidationTypeList (RangeExpression Range
    re)) = Range -> Maybe Range
    forall a. a -> Maybe a
    Just Range
    re
    maybeValidationRange ValidationType
    _ = Maybe Range
    forall a. Maybe a
    Nothing

    readListFormulas :: Formula -> Maybe ListOrRangeExpression
    readListFormulas :: Formula -> Maybe ListOrRangeExpression
    readListFormulas (Formula Text
    f) = Text -> Maybe ListOrRangeExpression
    readQuotedList Text
    f Maybe ListOrRangeExpression
    -> Maybe ListOrRangeExpression -> Maybe ListOrRangeExpression
    forall a. Maybe a -> Maybe a -> Maybe a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> Text -> Maybe ListOrRangeExpression
    forall {f :: * -> *}.
    Alternative f =>
    Text -> f ListOrRangeExpression
    readUnquotedCellRange Text
    f
      where
        readQuotedList :: Text -> Maybe ListOrRangeExpression
    readQuotedList Text
    t
            | Just Text
    t'  <- Text -> Text -> Maybe Text
    T.stripPrefix Text
    "\"" ((Char -> Bool) -> Text -> Text
    T.dropAround Char -> Bool
    isSpace Text
    t)
            , Just Text
    t'' <- Text -> Text -> Maybe Text
    T.stripSuffix Text
    "\"" Text
    t'
            = ListOrRangeExpression -> Maybe ListOrRangeExpression
    forall a. a -> Maybe a
    Just (ListOrRangeExpression -> Maybe ListOrRangeExpression)
    -> (ValidationList -> ListOrRangeExpression)
    -> ValidationList
    -> Maybe ListOrRangeExpression
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ValidationList -> ListOrRangeExpression
    ListExpression (ValidationList -> Maybe ListOrRangeExpression)
    -> ValidationList -> Maybe ListOrRangeExpression
    forall a b. (a -> b) -> a -> b
    $ (Text -> Text) -> ValidationList -> ValidationList
    forall a b. (a -> b) -> [a] -> [b]
    map ((Char -> Bool) -> Text -> Text
    T.dropAround Char -> Bool
    isSpace) (ValidationList -> ValidationList)
    -> ValidationList -> ValidationList
    forall a b. (a -> b) -> a -> b
    $ HasCallStack => Text -> Text -> ValidationList
    Text -> Text -> ValidationList
    T.splitOn Text
    "," Text
    t''
            | Bool
    otherwise = Maybe ListOrRangeExpression
    forall a. Maybe a
    Nothing
        readUnquotedCellRange :: Text -> f ListOrRangeExpression
    readUnquotedCellRange Text
    t =
          -- a CellRef expression of a range (this is not validated beyond the absence of quotes)
          -- note that the foreign sheet name can be 'single-quoted'
          let stripped :: Text
    stripped = (Char -> Bool) -> Text -> Text
    T.dropAround Char -> Bool
    isSpace Text
    t
            in Range -> ListOrRangeExpression
    RangeExpression (Text -> Range
    CellRef Text
    stripped) ListOrRangeExpression -> f () -> f ListOrRangeExpression
    forall a b. a -> f b -> f a
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
    <$ Bool -> f ()
    forall (f :: * -> *). Alternative f => Bool -> f ()
    guard (Bool -> Bool
    not (Text -> Bool
    T.null Text
    stripped))
      -- This parser expects a comma-separated list surrounded by quotation marks.
      -- Spaces around the quotation marks and commas are removed, but inner spaces
      -- are kept.
      --
      -- The parser seems to be consistent with how Excel treats list formulas, but
      -- I wasn't able to find a specification of the format.
      --
      -- Addendum: <dataValidation type="list" ...> undescriminately designates an actual list or a cell range.
      -- For a cell range validation, instead of a quoted list, it's an unquoted CellRef-like contents of the form:
      -- ActualSheetName!$C$2:$C$18

    readOpExpression2 :: Text -> Cursor -> [ValidationExpression]
    readOpExpression2 :: Text -> Cursor -> [ValidationExpression]
    readOpExpression2 Text
    op Cursor
    cur
        | Text
    op Text -> ValidationList -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [Text
    "between", Text
    "notBetween"] = do
            f1 <- Cursor
    cur Cursor -> (Cursor -> [Formula]) -> [Formula]
    forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
    $/ Name -> Axis
    element (Text -> Name
    n_ Text
    "formula1") Axis -> (Cursor -> [Formula]) -> Cursor -> [Formula]
    forall (m :: * -> *) a b c.
    Monad m =>
    (a -> m b) -> (b -> m c) -> a -> m c
    >=> Cursor -> [Formula]
    forall a. FromCursor a => Cursor -> [a]
    fromCursor
            f2 <- cur $/ element (n_ "formula2") >=> fromCursor
            readValExpression op [f1,f2]
    readOpExpression2 Text
    op Cursor
    cur = do
        f <- Cursor
    cur Cursor -> (Cursor -> [Formula]) -> [Formula]
    forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
    $/ Name -> Axis
    element (Text -> Name
    n_ Text
    "formula1") Axis -> (Cursor -> [Formula]) -> Cursor -> [Formula]
    forall (m :: * -> *) a b c.
    Monad m =>
    (a -> m b) -> (b -> m c) -> a -> m c
    >=> Cursor -> [Formula]
    forall a. FromCursor a => Cursor -> [a]
    fromCursor
        readValExpression op [f]

    readValidationTypeOpExp :: Text -> ValidationExpression -> [ValidationType]
    readValidationTypeOpExp :: Text -> ValidationExpression -> [ValidationType]
    readValidationTypeOpExp Text
    "date"       ValidationExpression
    oe = [ValidationExpression -> ValidationType
    ValidationTypeDate       ValidationExpression
    oe]
    readValidationTypeOpExp Text
    "decimal"    ValidationExpression
    oe = [ValidationExpression -> ValidationType
    ValidationTypeDecimal    ValidationExpression
    oe]
    readValidationTypeOpExp Text
    "textLength" ValidationExpression
    oe = [ValidationExpression -> ValidationType
    ValidationTypeTextLength ValidationExpression
    oe]
    readValidationTypeOpExp Text
    "time"       ValidationExpression
    oe = [ValidationExpression -> ValidationType
    ValidationTypeTime       ValidationExpression
    oe]
    readValidationTypeOpExp Text
    "whole"      ValidationExpression
    oe = [ValidationExpression -> ValidationType
    ValidationTypeWhole      ValidationExpression
    oe]
    readValidationTypeOpExp Text
    _ ValidationExpression
    _             = []

    readValExpression :: Text -> [Formula] -> [ValidationExpression]
    readValExpression :: Text -> [Formula] -> [ValidationExpression]
    readValExpression Text
    "between" [Formula
    f1, Formula
    f2]       = [Formula -> Formula -> ValidationExpression
    ValBetween Formula
    f1 Formula
    f2]
    readValExpression Text
    "equal" [Formula
    f]              = [Formula -> ValidationExpression
    ValEqual Formula
    f]
    readValExpression Text
    "greaterThan" [Formula
    f]        = [Formula -> ValidationExpression
    ValGreaterThan Formula
    f]
    readValExpression Text
    "greaterThanOrEqual" [Formula
    f] = [Formula -> ValidationExpression
    ValGreaterThanOrEqual Formula
    f]
    readValExpression Text
    "lessThan" [Formula
    f]           = [Formula -> ValidationExpression
    ValLessThan Formula
    f]
    readValExpression Text
    "lessThanOrEqual" [Formula
    f]    = [Formula -> ValidationExpression
    ValLessThanOrEqual Formula
    f]
    readValExpression Text
    "notBetween" [Formula
    f1, Formula
    f2]    = [Formula -> Formula -> ValidationExpression
    ValNotBetween Formula
    f1 Formula
    f2]
    readValExpression Text
    "notEqual" [Formula
    f]           = [Formula -> ValidationExpression
    ValNotEqual Formula
    f]
    readValExpression Text
    _ [Formula]
    _                      = []

    {-------------------------------------------------------------------------------
      Rendering
    -------------------------------------------------------------------------------}

    instance ToAttrVal ValidationType where
        toAttrVal :: ValidationType -> Text
    toAttrVal ValidationType
    ValidationTypeNone           = Text
    "none"
        toAttrVal (ValidationTypeCustom Formula
    _)     = Text
    "custom"
        toAttrVal (ValidationTypeDate ValidationExpression
    _)       = Text
    "date"
        toAttrVal (ValidationTypeDecimal ValidationExpression
    _)    = Text
    "decimal"
        toAttrVal (ValidationTypeList ListOrRangeExpression
    _)       = Text
    "list"
        toAttrVal (ValidationTypeTextLength ValidationExpression
    _) = Text
    "textLength"
        toAttrVal (ValidationTypeTime ValidationExpression
    _)       = Text
    "time"
        toAttrVal (ValidationTypeWhole ValidationExpression
    _)      = Text
    "whole"

    instance ToAttrVal ErrorStyle where
        toAttrVal :: ErrorStyle -> Text
    toAttrVal ErrorStyle
    ErrorStyleInformation = Text
    "information"
        toAttrVal ErrorStyle
    ErrorStyleStop        = Text
    "stop"
        toAttrVal ErrorStyle
    ErrorStyleWarning     = Text
    "warning"

    instance ToElement DataValidation where
        toElement :: Name -> DataValidation -> Element
    toElement Name
    nm DataValidation{Bool
    Maybe Text
    ErrorStyle
    ValidationType
    _dvAllowBlank :: DataValidation -> Bool
    _dvError :: DataValidation -> Maybe Text
    _dvErrorStyle :: DataValidation -> ErrorStyle
    _dvErrorTitle :: DataValidation -> Maybe Text
    _dvPrompt :: DataValidation -> Maybe Text
    _dvPromptTitle :: DataValidation -> Maybe Text
    _dvShowDropDown :: DataValidation -> Bool
    _dvShowErrorMessage :: DataValidation -> Bool
    _dvShowInputMessage :: DataValidation -> Bool
    _dvValidationType :: DataValidation -> ValidationType
    _dvAllowBlank :: Bool
    _dvError :: Maybe Text
    _dvErrorStyle :: ErrorStyle
    _dvErrorTitle :: Maybe Text
    _dvPrompt :: Maybe Text
    _dvPromptTitle :: Maybe Text
    _dvShowDropDown :: Bool
    _dvShowErrorMessage :: Bool
    _dvShowInputMessage :: Bool
    _dvValidationType :: ValidationType
    ..} = Element
            { elementName :: Name
    elementName       = Name
    nm
            , elementAttributes :: Map Name Text
    elementAttributes = [(Name, Text)] -> Map Name Text
    forall k a. Ord k => [(k, a)] -> Map k a
    M.fromList ([(Name, Text)] -> Map Name Text)
    -> ([Maybe (Name, Text)] -> [(Name, Text)])
    -> [Maybe (Name, Text)]
    -> Map Name Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Maybe (Name, Text)] -> [(Name, Text)]
    forall a. [Maybe a] -> [a]
    catMaybes ([Maybe (Name, Text)] -> Map Name Text)
    -> [Maybe (Name, Text)] -> Map Name Text
    forall a b. (a -> b) -> a -> b
    $
                [ (Name, Text) -> Maybe (Name, Text)
    forall a. a -> Maybe a
    Just ((Name, Text) -> Maybe (Name, Text))
    -> (Name, Text) -> Maybe (Name, Text)
    forall a b. (a -> b) -> a -> b
    $ Name
    "allowBlank"       Name -> Bool -> (Name, Text)
    forall a. ToAttrVal a => Name -> a -> (Name, Text)
    .=  Bool
    _dvAllowBlank
                ,        Name
    "error"            Name -> Maybe Text -> Maybe (Name, Text)
    forall a. ToAttrVal a => Name -> Maybe a -> Maybe (Name, Text)
    .=? Maybe Text
    _dvError
                , (Name, Text) -> Maybe (Name, Text)
    forall a. a -> Maybe a
    Just ((Name, Text) -> Maybe (Name, Text))
    -> (Name, Text) -> Maybe (Name, Text)
    forall a b. (a -> b) -> a -> b
    $ Name
    "errorStyle"       Name -> ErrorStyle -> (Name, Text)
    forall a. ToAttrVal a => Name -> a -> (Name, Text)
    .=  ErrorStyle
    _dvErrorStyle
                ,        Name
    "errorTitle"       Name -> Maybe Text -> Maybe (Name, Text)
    forall a. ToAttrVal a => Name -> Maybe a -> Maybe (Name, Text)
    .=? Maybe Text
    _dvErrorTitle
                ,        Name
    "operator"         Name -> Maybe Text -> Maybe (Name, Text)
    forall a. ToAttrVal a => Name -> Maybe a -> Maybe (Name, Text)
    .=? Maybe Text
    op
                ,        Name
    "prompt"           Name -> Maybe Text -> Maybe (Name, Text)
    forall a. ToAttrVal a => Name -> Maybe a -> Maybe (Name, Text)
    .=? Maybe Text
    _dvPrompt
                ,        Name
    "promptTitle"      Name -> Maybe Text -> Maybe (Name, Text)
    forall a. ToAttrVal a => Name -> Maybe a -> Maybe (Name, Text)
    .=? Maybe Text
    _dvPromptTitle
                , (Name, Text) -> Maybe (Name, Text)
    forall a. a -> Maybe a
    Just ((Name, Text) -> Maybe (Name, Text))
    -> (Name, Text) -> Maybe (Name, Text)
    forall a b. (a -> b) -> a -> b
    $ Name
    "showDropDown"     Name -> Bool -> (Name, Text)
    forall a. ToAttrVal a => Name -> a -> (Name, Text)
    .=  Bool
    _dvShowDropDown
                , (Name, Text) -> Maybe (Name, Text)
    forall a. a -> Maybe a
    Just ((Name, Text) -> Maybe (Name, Text))
    -> (Name, Text) -> Maybe (Name, Text)
    forall a b. (a -> b) -> a -> b
    $ Name
    "showErrorMessage" Name -> Bool -> (Name, Text)
    forall a. ToAttrVal a => Name -> a -> (Name, Text)
    .=  Bool
    _dvShowErrorMessage
                , (Name, Text) -> Maybe (Name, Text)
    forall a. a -> Maybe a
    Just ((Name, Text) -> Maybe (Name, Text))
    -> (Name, Text) -> Maybe (Name, Text)
    forall a b. (a -> b) -> a -> b
    $ Name
    "showInputMessage" Name -> Bool -> (Name, Text)
    forall a. ToAttrVal a => Name -> a -> (Name, Text)
    .=  Bool
    _dvShowInputMessage
                , (Name, Text) -> Maybe (Name, Text)
    forall a. a -> Maybe a
    Just ((Name, Text) -> Maybe (Name, Text))
    -> (Name, Text) -> Maybe (Name, Text)
    forall a b. (a -> b) -> a -> b
    $ Name
    "type"             Name -> ValidationType -> (Name, Text)
    forall a. ToAttrVal a => Name -> a -> (Name, Text)
    .=  ValidationType
    _dvValidationType
                ]
            , elementNodes :: [Node]
    elementNodes      = [Maybe Node] -> [Node]
    forall a. [Maybe a] -> [a]
    catMaybes
                [ (Formula -> Node) -> Maybe Formula -> Maybe Node
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (Element -> Node
    NodeElement (Element -> Node) -> (Formula -> Element) -> Formula -> Node
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Name -> Formula -> Element
    forall a. ToElement a => Name -> a -> Element
    toElement Name
    "formula1") Maybe Formula
    f1
                , (Formula -> Node) -> Maybe Formula -> Maybe Node
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (Element -> Node
    NodeElement (Element -> Node) -> (Formula -> Element) -> Formula -> Node
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Name -> Formula -> Element
    forall a. ToElement a => Name -> a -> Element
    toElement Name
    "formula2") Maybe Formula
    f2
                ]
            }
          where
            opExp :: (a, a, c) -> (Maybe a, Maybe a, c)
    opExp (a
    o,a
    f1',c
    f2') = (a -> Maybe a
    forall a. a -> Maybe a
    Just a
    o, a -> Maybe a
    forall a. a -> Maybe a
    Just a
    f1', c
    f2')

            op    :: Maybe Text
            f1,f2 :: Maybe Formula
            (Maybe Text
    op,Maybe Formula
    f1,Maybe Formula
    f2) = case ValidationType
    _dvValidationType of
              ValidationType
    ValidationTypeNone         -> (Maybe Text
    forall a. Maybe a
    Nothing, Maybe Formula
    forall a. Maybe a
    Nothing, Maybe Formula
    forall a. Maybe a
    Nothing)
              ValidationTypeCustom Formula
    f     -> (Maybe Text
    forall a. Maybe a
    Nothing, Formula -> Maybe Formula
    forall a. a -> Maybe a
    Just Formula
    f, Maybe Formula
    forall a. Maybe a
    Nothing)
              ValidationTypeDate ValidationExpression
    f       -> (Text, Formula, Maybe Formula)
    -> (Maybe Text, Maybe Formula, Maybe Formula)
    forall {a} {a} {c}. (a, a, c) -> (Maybe a, Maybe a, c)
    opExp ((Text, Formula, Maybe Formula)
     -> (Maybe Text, Maybe Formula, Maybe Formula))
    -> (Text, Formula, Maybe Formula)
    -> (Maybe Text, Maybe Formula, Maybe Formula)
    forall a b. (a -> b) -> a -> b
    $ ValidationExpression -> (Text, Formula, Maybe Formula)
    viewValidationExpression ValidationExpression
    f
              ValidationTypeDecimal ValidationExpression
    f    -> (Text, Formula, Maybe Formula)
    -> (Maybe Text, Maybe Formula, Maybe Formula)
    forall {a} {a} {c}. (a, a, c) -> (Maybe a, Maybe a, c)
    opExp ((Text, Formula, Maybe Formula)
     -> (Maybe Text, Maybe Formula, Maybe Formula))
    -> (Text, Formula, Maybe Formula)
    -> (Maybe Text, Maybe Formula, Maybe Formula)
    forall a b. (a -> b) -> a -> b
    $ ValidationExpression -> (Text, Formula, Maybe Formula)
    viewValidationExpression ValidationExpression
    f
              ValidationTypeTextLength ValidationExpression
    f -> (Text, Formula, Maybe Formula)
    -> (Maybe Text, Maybe Formula, Maybe Formula)
    forall {a} {a} {c}. (a, a, c) -> (Maybe a, Maybe a, c)
    opExp ((Text, Formula, Maybe Formula)
     -> (Maybe Text, Maybe Formula, Maybe Formula))
    -> (Text, Formula, Maybe Formula)
    -> (Maybe Text, Maybe Formula, Maybe Formula)
    forall a b. (a -> b) -> a -> b
    $ ValidationExpression -> (Text, Formula, Maybe Formula)
    viewValidationExpression ValidationExpression
    f
              ValidationTypeTime ValidationExpression
    f       -> (Text, Formula, Maybe Formula)
    -> (Maybe Text, Maybe Formula, Maybe Formula)
    forall {a} {a} {c}. (a, a, c) -> (Maybe a, Maybe a, c)
    opExp ((Text, Formula, Maybe Formula)
     -> (Maybe Text, Maybe Formula, Maybe Formula))
    -> (Text, Formula, Maybe Formula)
    -> (Maybe Text, Maybe Formula, Maybe Formula)
    forall a b. (a -> b) -> a -> b
    $ ValidationExpression -> (Text, Formula, Maybe Formula)
    viewValidationExpression ValidationExpression
    f
              ValidationTypeWhole ValidationExpression
    f      -> (Text, Formula, Maybe Formula)
    -> (Maybe Text, Maybe Formula, Maybe Formula)
    forall {a} {a} {c}. (a, a, c) -> (Maybe a, Maybe a, c)
    opExp ((Text, Formula, Maybe Formula)
     -> (Maybe Text, Maybe Formula, Maybe Formula))
    -> (Text, Formula, Maybe Formula)
    -> (Maybe Text, Maybe Formula, Maybe Formula)
    forall a b. (a -> b) -> a -> b
    $ ValidationExpression -> (Text, Formula, Maybe Formula)
    viewValidationExpression ValidationExpression
    f
              ValidationTypeList ListOrRangeExpression
    as      ->
                let renderPlainList :: ValidationList -> Text
    renderPlainList ValidationList
    l =
                      let csvFy :: ValidationList -> Text
    csvFy ValidationList
    xs = Text -> ValidationList -> Text
    T.intercalate Text
    "," ValidationList
    xs
                          reQuote :: Text -> Text
    reQuote Text
    x = Char
    '"' Char -> Text -> Text
    `T.cons`  Text
    x Text -> Char -> Text
    `T.snoc` Char
    '"'
                        in Text -> Text
    reQuote (ValidationList -> Text
    csvFy ValidationList
    l)
                    f :: Formula
    f = Text -> Formula
    Formula (Text -> Formula) -> Text -> Formula
    forall a b. (a -> b) -> a -> b
    $
                          case ListOrRangeExpression
    as of
                            RangeExpression Range
    re -> Range -> Text
    unCellRef Range
    re
                            ListExpression ValidationList
    le -> ValidationList -> Text
    renderPlainList ValidationList
    le
                in  (Maybe Text
    forall a. Maybe a
    Nothing, Formula -> Maybe Formula
    forall a. a -> Maybe a
    Just Formula
    f, Maybe Formula
    forall a. Maybe a
    Nothing)

    viewValidationExpression :: ValidationExpression -> (Text, Formula, Maybe Formula)
    viewValidationExpression :: ValidationExpression -> (Text, Formula, Maybe Formula)
    viewValidationExpression (ValBetween Formula
    f1 Formula
    f2)         = (Text
    "between",            Formula
    f1, Formula -> Maybe Formula
    forall a. a -> Maybe a
    Just Formula
    f2)
    viewValidationExpression (ValEqual Formula
    f)               = (Text
    "equal",              Formula
    f,  Maybe Formula
    forall a. Maybe a
    Nothing)
    viewValidationExpression (ValGreaterThan Formula
    f)         = (Text
    "greaterThan",        Formula
    f,  Maybe Formula
    forall a. Maybe a
    Nothing)
    viewValidationExpression (ValGreaterThanOrEqual Formula
    f)  = (Text
    "greaterThanOrEqual", Formula
    f,  Maybe Formula
    forall a. Maybe a
    Nothing)
    viewValidationExpression (ValLessThan Formula
    f)            = (Text
    "lessThan",           Formula
    f,  Maybe Formula
    forall a. Maybe a
    Nothing)
    viewValidationExpression (ValLessThanOrEqual Formula
    f)     = (Text
    "lessThanOrEqual",    Formula
    f,  Maybe Formula
    forall a. Maybe a
    Nothing)
    viewValidationExpression (ValNotBetween Formula
    f1 Formula
    f2)      = (Text
    "notBetween",         Formula
    f1, Formula -> Maybe Formula
    forall a. a -> Maybe a
    Just Formula
    f2)
    viewValidationExpression (ValNotEqual Formula
    f)            = (Text
    "notEqual",           Formula
    f,  Maybe Formula
    forall a. Maybe a
    Nothing)