--------------------------------------------------------------------------------
--  See end of this file for licence information.
--------------------------------------------------------------------------------
-- |
--  Module      :  Rules
--  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin, 2011, 2012, 2022, 2024 Douglas Burke
--  License     :  GPL V2
--
--  Maintainer  :  Douglas Burke
--  Stability   :  experimental
--  Portability :  H98
--
--  This module collects references and provides access to all of the
--  rulesets, variable binding modifiers and variable binding filters
--  built in to Swish.
--
--------------------------------------------------------------------------------

module Swish.RDF.BuiltIn.Rules
    ( findRDFOpenVarBindingModifier
    , rdfRulesetMap
    , allRulesets, allDatatypeRulesets
    )
where

import Swish.Datatype (typeRules, typeMkModifiers)
import Swish.Namespace (ScopedName)
import Swish.Ruleset (getRulesetNamespace)
import Swish.VarBinding (openVbmName, nullVarBindingModify, makeVarFilterModify, varFilterEQ, varFilterNE)

import Swish.RDF.BuiltIn.Datatypes (allDatatypes)
import Swish.RDF.Ruleset (RDFRuleset, RDFRulesetMap)
import Swish.RDF.ProofContext (rulesetRDF, rulesetRDFS, rulesetRDFD)

import Swish.RDF.VarBinding
    ( RDFOpenVarBindingModify
    , rdfVarBindingUriRef, rdfVarBindingBlank
    , rdfVarBindingLiteral
    , rdfVarBindingUntypedLiteral, rdfVarBindingTypedLiteral
    , rdfVarBindingXMLLiteral, rdfVarBindingDatatyped
    , rdfVarBindingMemberProp
    )

import qualified Data.Map as M

------------------------------------------------------------
--  Declare variable binding filters list
------------------------------------------------------------

-- |List of rdfOpenVarBindingModify values for predefined filters
--
rdfVarBindingFilters :: [RDFOpenVarBindingModify]
rdfVarBindingFilters :: [RDFOpenVarBindingModify]
rdfVarBindingFilters =
    [ (RDFLabel -> VarBindingFilter RDFLabel RDFLabel)
-> RDFOpenVarBindingModify
forall {a} {a} {b}.
(a -> VarBindingFilter a b) -> [a] -> VarBindingModify a b
filter1 RDFLabel -> VarBindingFilter RDFLabel RDFLabel
rdfVarBindingUriRef
    , (RDFLabel -> VarBindingFilter RDFLabel RDFLabel)
-> RDFOpenVarBindingModify
forall {a} {a} {b}.
(a -> VarBindingFilter a b) -> [a] -> VarBindingModify a b
filter1 RDFLabel -> VarBindingFilter RDFLabel RDFLabel
rdfVarBindingBlank
    , (RDFLabel -> VarBindingFilter RDFLabel RDFLabel)
-> RDFOpenVarBindingModify
forall {a} {a} {b}.
(a -> VarBindingFilter a b) -> [a] -> VarBindingModify a b
filter1 RDFLabel -> VarBindingFilter RDFLabel RDFLabel
rdfVarBindingLiteral
    , (RDFLabel -> VarBindingFilter RDFLabel RDFLabel)
-> RDFOpenVarBindingModify
forall {a} {a} {b}.
(a -> VarBindingFilter a b) -> [a] -> VarBindingModify a b
filter1 RDFLabel -> VarBindingFilter RDFLabel RDFLabel
rdfVarBindingUntypedLiteral
    , (RDFLabel -> VarBindingFilter RDFLabel RDFLabel)
-> RDFOpenVarBindingModify
forall {a} {a} {b}.
(a -> VarBindingFilter a b) -> [a] -> VarBindingModify a b
filter1 RDFLabel -> VarBindingFilter RDFLabel RDFLabel
rdfVarBindingTypedLiteral
    , (RDFLabel -> VarBindingFilter RDFLabel RDFLabel)
-> RDFOpenVarBindingModify
forall {a} {a} {b}.
(a -> VarBindingFilter a b) -> [a] -> VarBindingModify a b
filter1 RDFLabel -> VarBindingFilter RDFLabel RDFLabel
rdfVarBindingXMLLiteral
    , (RDFLabel -> VarBindingFilter RDFLabel RDFLabel)
-> RDFOpenVarBindingModify
forall {a} {a} {b}.
(a -> VarBindingFilter a b) -> [a] -> VarBindingModify a b
filter1 RDFLabel -> VarBindingFilter RDFLabel RDFLabel
rdfVarBindingMemberProp
    , (RDFLabel -> RDFLabel -> VarBindingFilter RDFLabel RDFLabel)
-> RDFOpenVarBindingModify
forall {b} {a} {b}.
(b -> b -> VarBindingFilter a b) -> [b] -> VarBindingModify a b
filter2 RDFLabel -> RDFLabel -> VarBindingFilter RDFLabel RDFLabel
rdfVarBindingDatatyped
    -- , filterN nullVarBindingModify
    , (RDFLabel -> RDFLabel -> VarBindingFilter RDFLabel RDFLabel)
-> RDFOpenVarBindingModify
forall {b} {a} {b}.
(b -> b -> VarBindingFilter a b) -> [b] -> VarBindingModify a b
filter2 RDFLabel -> RDFLabel -> VarBindingFilter RDFLabel RDFLabel
forall b a. Eq b => a -> a -> VarBindingFilter a b
varFilterEQ
    , (RDFLabel -> RDFLabel -> VarBindingFilter RDFLabel RDFLabel)
-> RDFOpenVarBindingModify
forall {b} {a} {b}.
(b -> b -> VarBindingFilter a b) -> [b] -> VarBindingModify a b
filter2 RDFLabel -> RDFLabel -> VarBindingFilter RDFLabel RDFLabel
forall b a. Eq b => a -> a -> VarBindingFilter a b
varFilterNE
    ]
    where
      -- Swish.VarBinding.openVbmName seems to require that the label
      -- list not be evaluated which means that we end up delaying
      -- the evaluation of the list as long as possible (i.e. when
      -- evaluating the arguments for `f`).
      --
      filter1 :: (a -> VarBindingFilter a b) -> [a] -> VarBindingModify a b
filter1 a -> VarBindingFilter a b
f [a]
lbs = VarBindingFilter a b -> VarBindingModify a b
forall a b. VarBindingFilter a b -> VarBindingModify a b
makeVarFilterModify (VarBindingFilter a b -> VarBindingModify a b)
-> (a -> VarBindingFilter a b) -> a -> VarBindingModify a b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> VarBindingFilter a b
f (a -> VarBindingModify a b) -> a -> VarBindingModify a b
forall a b. (a -> b) -> a -> b
$ case [a]
lbs of
        (a
lb:[a]
_) -> a
lb
        [] -> [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"unexpected empty list"

      filter2 :: (b -> b -> VarBindingFilter a b) -> [b] -> VarBindingModify a b
filter2 b -> b -> VarBindingFilter a b
f [b]
lbs = VarBindingFilter a b -> VarBindingModify a b
forall a b. VarBindingFilter a b -> VarBindingModify a b
makeVarFilterModify (VarBindingFilter a b -> VarBindingModify a b)
-> ((b, b) -> VarBindingFilter a b)
-> (b, b)
-> VarBindingModify a b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (b -> b -> VarBindingFilter a b) -> (b, b) -> VarBindingFilter a b
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry b -> b -> VarBindingFilter a b
f ((b, b) -> VarBindingModify a b) -> (b, b) -> VarBindingModify a b
forall a b. (a -> b) -> a -> b
$ case [b]
lbs of
        (b
lb1:b
lb2:[b]
_) -> (b
lb1, b
lb2)
        [b]
_ -> [Char] -> (b, b)
forall a. HasCallStack => [Char] -> a
error [Char]
"requires at least 2 elements in the list"


------------------------------------------------------------
--  Declare variable binding modifiers map
------------------------------------------------------------

rdfVarBindingModifiers :: [RDFOpenVarBindingModify]
rdfVarBindingModifiers :: [RDFOpenVarBindingModify]
rdfVarBindingModifiers =
    [ RDFOpenVarBindingModify
forall a b. OpenVarBindingModify a b
nullVarBindingModify
    ]

------------------------------------------------------------
--  Find a named built-in OpenVarBindingModifier
------------------------------------------------------------

allOpenVarBindingModify :: [RDFOpenVarBindingModify]
allOpenVarBindingModify :: [RDFOpenVarBindingModify]
allOpenVarBindingModify =
    [RDFOpenVarBindingModify]
rdfVarBindingFilters    [RDFOpenVarBindingModify]
-> [RDFOpenVarBindingModify] -> [RDFOpenVarBindingModify]
forall a. [a] -> [a] -> [a]
++
    [RDFOpenVarBindingModify]
rdfVarBindingModifiers  [RDFOpenVarBindingModify]
-> [RDFOpenVarBindingModify] -> [RDFOpenVarBindingModify]
forall a. [a] -> [a] -> [a]
++
    [RDFOpenVarBindingModify]
dtsVarBindingModifiers

dtsVarBindingModifiers :: [RDFOpenVarBindingModify]
-- dtsVarBindingModifiers = concatMap dtVarBindingModifiers allDatatypes
dtsVarBindingModifiers :: [RDFOpenVarBindingModify]
dtsVarBindingModifiers = (Datatype RDFGraph RDFLabel RDFLabel -> [RDFOpenVarBindingModify])
-> [Datatype RDFGraph RDFLabel RDFLabel]
-> [RDFOpenVarBindingModify]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Datatype RDFGraph RDFLabel RDFLabel -> [RDFOpenVarBindingModify]
forall ex lb vn. Datatype ex lb vn -> [OpenVarBindingModify lb vn]
typeMkModifiers [Datatype RDFGraph RDFLabel RDFLabel]
allDatatypes

{-
dtVarBindingModifiers dtval =
    map (makeRdfDtOpenVarBindingModify dtval) (tvalMod dtval)
-}

-- | Find the named open variable binding modifier.
findRDFOpenVarBindingModifier :: ScopedName -> Maybe RDFOpenVarBindingModify
findRDFOpenVarBindingModifier :: ScopedName -> Maybe RDFOpenVarBindingModify
findRDFOpenVarBindingModifier ScopedName
nam =
    ScopedName
-> Map ScopedName RDFOpenVarBindingModify
-> Maybe RDFOpenVarBindingModify
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup ScopedName
nam (Map ScopedName RDFOpenVarBindingModify
 -> Maybe RDFOpenVarBindingModify)
-> Map ScopedName RDFOpenVarBindingModify
-> Maybe RDFOpenVarBindingModify
forall a b. (a -> b) -> a -> b
$ [(ScopedName, RDFOpenVarBindingModify)]
-> Map ScopedName RDFOpenVarBindingModify
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(ScopedName, RDFOpenVarBindingModify)]
 -> Map ScopedName RDFOpenVarBindingModify)
-> [(ScopedName, RDFOpenVarBindingModify)]
-> Map ScopedName RDFOpenVarBindingModify
forall a b. (a -> b) -> a -> b
$ (RDFOpenVarBindingModify -> (ScopedName, RDFOpenVarBindingModify))
-> [RDFOpenVarBindingModify]
-> [(ScopedName, RDFOpenVarBindingModify)]
forall a b. (a -> b) -> [a] -> [b]
map (\RDFOpenVarBindingModify
ovbm -> (RDFOpenVarBindingModify -> ScopedName
forall lb vn. OpenVarBindingModify lb vn -> ScopedName
openVbmName RDFOpenVarBindingModify
ovbm, RDFOpenVarBindingModify
ovbm))
                                [RDFOpenVarBindingModify]
allOpenVarBindingModify

------------------------------------------------------------
--  Lookup map for built-in rulesets
------------------------------------------------------------

-- | A 'LookupMap' of 'allRulesets'.
rdfRulesetMap :: RDFRulesetMap
rdfRulesetMap :: RDFRulesetMap
rdfRulesetMap = [(Namespace, Ruleset RDFGraph)] -> RDFRulesetMap
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(Namespace, Ruleset RDFGraph)] -> RDFRulesetMap)
-> [(Namespace, Ruleset RDFGraph)] -> RDFRulesetMap
forall a b. (a -> b) -> a -> b
$ (Ruleset RDFGraph -> (Namespace, Ruleset RDFGraph))
-> [Ruleset RDFGraph] -> [(Namespace, Ruleset RDFGraph)]
forall a b. (a -> b) -> [a] -> [b]
map (\Ruleset RDFGraph
r -> (Ruleset RDFGraph -> Namespace
forall ex. Ruleset ex -> Namespace
getRulesetNamespace Ruleset RDFGraph
r, Ruleset RDFGraph
r)) [Ruleset RDFGraph]
allRulesets

-- | All the rule sets known to Swish.
allRulesets :: [RDFRuleset]
allRulesets :: [Ruleset RDFGraph]
allRulesets =
    [ Ruleset RDFGraph
rulesetRDF
    , Ruleset RDFGraph
rulesetRDFS
    , Ruleset RDFGraph
rulesetRDFD
    ]
    [Ruleset RDFGraph] -> [Ruleset RDFGraph] -> [Ruleset RDFGraph]
forall a. [a] -> [a] -> [a]
++ [Ruleset RDFGraph]
allDatatypeRulesets

-- | The data type rule sets known to Swish.
allDatatypeRulesets :: [RDFRuleset]
allDatatypeRulesets :: [Ruleset RDFGraph]
allDatatypeRulesets = (Datatype RDFGraph RDFLabel RDFLabel -> Ruleset RDFGraph)
-> [Datatype RDFGraph RDFLabel RDFLabel] -> [Ruleset RDFGraph]
forall a b. (a -> b) -> [a] -> [b]
map Datatype RDFGraph RDFLabel RDFLabel -> Ruleset RDFGraph
forall ex lb vn. Datatype ex lb vn -> Ruleset ex
typeRules [Datatype RDFGraph RDFLabel RDFLabel]
allDatatypes

--------------------------------------------------------------------------------
--
--  Copyright (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
--    2011, 2012, 2022, 2024 Douglas Burke
--  All rights reserved.
--
--  This file is part of Swish.
--
--  Swish is free software; you can redistribute it and/or modify
--  it under the terms of the GNU General Public License as published by
--  the Free Software Foundation; either version 2 of the License, or
--  (at your option) any later version.
--
--  Swish is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--  GNU General Public License for more details.
--
--  You should have received a copy of the GNU General Public License
--  along with Swish; if not, write to:
--    The Free Software Foundation, Inc.,
--    59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
--
--------------------------------------------------------------------------------