{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
module Swish.RDF.Ruleset
(
RDFFormula, RDFRule, RDFRuleMap
, RDFClosure, RDFRuleset, RDFRulesetMap
, nullRDFFormula
, GraphClosure(..), makeGraphClosureRule
, makeRDFGraphFromN3Builder
, makeRDFFormula
, makeRDFClosureRule
, makeN3ClosureRule
, makeN3ClosureSimpleRule
, makeN3ClosureModifyRule
, makeN3ClosureAllocatorRule
, makeNodeAllocTo
, graphClosureFwdApply, graphClosureBwdApply
)
where
import Swish.Namespace (Namespace, ScopedName)
import Swish.Namespace (makeNSScopedName, namespaceToBuilder)
import Swish.QName (LName)
import Swish.Rule (Formula(..), Rule(..), RuleMap)
import Swish.Rule (fwdCheckInference, nullSN)
import Swish.Ruleset (Ruleset(..), RulesetMap)
import Swish.GraphClass (Label(..), ArcSet, LDGraph(..))
import Swish.VarBinding (VarBindingModify(..))
import Swish.VarBinding (makeVarBinding, applyVarBinding, joinVarBindings, vbmCompose, varBindingId)
import Swish.RDF.Query
( rdfQueryFind
, rdfQueryBack, rdfQueryBackModify
, rdfQuerySubs
, rdfQuerySubsBlank
)
import Swish.RDF.Graph
( RDFLabel(..), RDFGraph, RDFArcSet
, makeBlank, newNodes
, merge, allLabels
, toRDFGraph)
import Swish.RDF.VarBinding (RDFVarBinding, RDFVarBindingModify)
import Swish.RDF.Parser.N3 (parseN3)
import Swish.RDF.Vocabulary (swishName, namespaceRDF, namespaceRDFS)
import Swish.Utils.ListHelpers (flist)
import Data.List (nub)
import Data.Maybe (fromMaybe)
#if (!defined(__GLASGOW_HASKELL__)) || (__GLASGOW_HASKELL__ < 710)
import Data.Monoid (Monoid(..))
#endif
import qualified Data.Set as S
import qualified Data.Text.Lazy.Builder as B
type RDFFormula = Formula RDFGraph
type RDFRule = Rule RDFGraph
type RDFRuleMap = RuleMap RDFGraph
type RDFClosure = GraphClosure RDFLabel
type RDFRuleset = Ruleset RDFGraph
type RDFRulesetMap = RulesetMap RDFGraph
nullRDFFormula :: Formula RDFGraph
nullRDFFormula :: Formula RDFGraph
nullRDFFormula = Formula
{ formName :: ScopedName
formName = LName -> ScopedName
nullSN LName
"nullRDFGraph"
, formExpr :: RDFGraph
formExpr = forall a. Monoid a => a
mempty
}
data GraphClosure lb = GraphClosure
{ forall lb. GraphClosure lb -> ScopedName
nameGraphRule :: ScopedName
, forall lb. GraphClosure lb -> ArcSet lb
ruleAnt :: ArcSet lb
, forall lb. GraphClosure lb -> ArcSet lb
ruleCon :: ArcSet lb
, forall lb. GraphClosure lb -> VarBindingModify lb lb
ruleModify :: VarBindingModify lb lb
}
instance (Label lb) => Eq (GraphClosure lb) where
GraphClosure lb
c1 == :: GraphClosure lb -> GraphClosure lb -> Bool
== GraphClosure lb
c2 = forall lb. GraphClosure lb -> ScopedName
nameGraphRule GraphClosure lb
c1 forall a. Eq a => a -> a -> Bool
== forall lb. GraphClosure lb -> ScopedName
nameGraphRule GraphClosure lb
c2 Bool -> Bool -> Bool
&&
forall lb. GraphClosure lb -> ArcSet lb
ruleAnt GraphClosure lb
c1 forall a. Eq a => a -> a -> Bool
== forall lb. GraphClosure lb -> ArcSet lb
ruleAnt GraphClosure lb
c2 Bool -> Bool -> Bool
&&
forall lb. GraphClosure lb -> ArcSet lb
ruleCon GraphClosure lb
c1 forall a. Eq a => a -> a -> Bool
== forall lb. GraphClosure lb -> ArcSet lb
ruleCon GraphClosure lb
c2
instance Show (GraphClosure lb) where
show :: GraphClosure lb -> String
show GraphClosure lb
c = String
"GraphClosure " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show (forall lb. GraphClosure lb -> ScopedName
nameGraphRule GraphClosure lb
c)
makeGraphClosureRule :: GraphClosure RDFLabel -> Rule RDFGraph
makeGraphClosureRule :: GraphClosure RDFLabel -> Rule RDFGraph
makeGraphClosureRule GraphClosure RDFLabel
grc = Rule RDFGraph
newrule
where
newrule :: Rule RDFGraph
newrule = Rule
{ ruleName :: ScopedName
ruleName = forall lb. GraphClosure lb -> ScopedName
nameGraphRule GraphClosure RDFLabel
grc
, fwdApply :: [RDFGraph] -> [RDFGraph]
fwdApply = GraphClosure RDFLabel -> [RDFGraph] -> [RDFGraph]
graphClosureFwdApply GraphClosure RDFLabel
grc
, bwdApply :: RDFGraph -> [[RDFGraph]]
bwdApply = GraphClosure RDFLabel -> RDFGraph -> [[RDFGraph]]
graphClosureBwdApply GraphClosure RDFLabel
grc
, checkInference :: [RDFGraph] -> RDFGraph -> Bool
checkInference = forall ex. Eq ex => Rule ex -> [ex] -> ex -> Bool
fwdCheckInference Rule RDFGraph
newrule
}
graphClosureFwdApply ::
GraphClosure RDFLabel
-> [RDFGraph]
-> [RDFGraph]
graphClosureFwdApply :: GraphClosure RDFLabel -> [RDFGraph] -> [RDFGraph]
graphClosureFwdApply GraphClosure RDFLabel
grc [RDFGraph]
grs =
let gr :: RDFGraph
gr = if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [RDFGraph]
grs then forall a. Monoid a => a
mempty else forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 forall (lg :: * -> *) lb.
(LDGraph lg lb, Ord lb) =>
lg lb -> lg lb -> lg lb
addGraphs [RDFGraph]
grs
vars :: [RDFVarBinding]
vars = RDFArcSet -> RDFGraph -> [RDFVarBinding]
queryFind (forall lb. GraphClosure lb -> ArcSet lb
ruleAnt GraphClosure RDFLabel
grc) RDFGraph
gr
varm :: [RDFVarBinding]
varm = forall a b.
VarBindingModify a b -> [VarBinding a b] -> [VarBinding a b]
vbmApply (forall lb. GraphClosure lb -> VarBindingModify lb lb
ruleModify GraphClosure RDFLabel
grc) [RDFVarBinding]
vars
cons :: [RDFGraph]
cons = [RDFVarBinding] -> RDFArcSet -> [RDFGraph]
querySubs [RDFVarBinding]
varm (forall lb. GraphClosure lb -> ArcSet lb
ruleCon GraphClosure RDFLabel
grc)
in
if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [RDFGraph]
cons then [] else [forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 forall (lg :: * -> *) lb.
(LDGraph lg lb, Ord lb) =>
lg lb -> lg lb -> lg lb
addGraphs [RDFGraph]
cons]
graphClosureBwdApply :: GraphClosure RDFLabel -> RDFGraph -> [[RDFGraph]]
graphClosureBwdApply :: GraphClosure RDFLabel -> RDFGraph -> [[RDFGraph]]
graphClosureBwdApply GraphClosure RDFLabel
grc RDFGraph
gr =
let vars :: [[RDFVarBinding]]
vars = forall a b.
VarBindingModify a b -> [[VarBinding a b]] -> [[VarBinding a b]]
rdfQueryBackModify (forall lb. GraphClosure lb -> VarBindingModify lb lb
ruleModify GraphClosure RDFLabel
grc) forall a b. (a -> b) -> a -> b
$
RDFArcSet -> RDFGraph -> [[RDFVarBinding]]
queryBack (forall lb. GraphClosure lb -> ArcSet lb
ruleCon GraphClosure RDFLabel
grc) RDFGraph
gr
varn :: [[RDFVarBinding]]
varn = forall a b. (a -> b) -> [a] -> [b]
map forall a. Eq a => [a] -> [a]
nub [[RDFVarBinding]]
vars
in
[ [forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 forall lb. Label lb => NSGraph lb -> NSGraph lb -> NSGraph lb
merge (forall a. Eq a => [a] -> [a]
nub [RDFGraph]
ante)]
| [RDFVarBinding]
vs <- [[RDFVarBinding]]
varn
, let ante :: [RDFGraph]
ante = [RDFVarBinding] -> RDFArcSet -> [RDFGraph]
querySubsBlank [RDFVarBinding]
vs (forall lb. GraphClosure lb -> ArcSet lb
ruleAnt GraphClosure RDFLabel
grc) ]
queryFind :: RDFArcSet -> RDFGraph -> [RDFVarBinding]
queryFind :: RDFArcSet -> RDFGraph -> [RDFVarBinding]
queryFind RDFArcSet
qas = RDFGraph -> RDFGraph -> [RDFVarBinding]
rdfQueryFind (RDFArcSet -> RDFGraph
toRDFGraph RDFArcSet
qas)
queryBack :: RDFArcSet -> RDFGraph -> [[RDFVarBinding]]
queryBack :: RDFArcSet -> RDFGraph -> [[RDFVarBinding]]
queryBack RDFArcSet
qas = RDFGraph -> RDFGraph -> [[RDFVarBinding]]
rdfQueryBack (RDFArcSet -> RDFGraph
toRDFGraph RDFArcSet
qas)
querySubs :: [RDFVarBinding] -> RDFArcSet -> [RDFGraph]
querySubs :: [RDFVarBinding] -> RDFArcSet -> [RDFGraph]
querySubs [RDFVarBinding]
vars = [RDFVarBinding] -> RDFGraph -> [RDFGraph]
rdfQuerySubs [RDFVarBinding]
vars forall b c a. (b -> c) -> (a -> b) -> a -> c
. RDFArcSet -> RDFGraph
toRDFGraph
querySubsBlank :: [RDFVarBinding] -> RDFArcSet -> [RDFGraph]
querySubsBlank :: [RDFVarBinding] -> RDFArcSet -> [RDFGraph]
querySubsBlank [RDFVarBinding]
vars = [RDFVarBinding] -> RDFGraph -> [RDFGraph]
rdfQuerySubsBlank [RDFVarBinding]
vars forall b c a. (b -> c) -> (a -> b) -> a -> c
. RDFArcSet -> RDFGraph
toRDFGraph
mkPrefix :: Namespace -> B.Builder
mkPrefix :: Namespace -> Builder
mkPrefix = Namespace -> Builder
namespaceToBuilder
prefixRDF :: B.Builder
prefixRDF :: Builder
prefixRDF =
forall a. Monoid a => [a] -> a
mconcat
[ Namespace -> Builder
mkPrefix Namespace
namespaceRDF
, Namespace -> Builder
mkPrefix Namespace
namespaceRDFS
]
makeRDFGraphFromN3Builder :: B.Builder -> RDFGraph
makeRDFGraphFromN3Builder :: Builder -> RDFGraph
makeRDFGraphFromN3Builder Builder
b =
let t :: Text
t = Builder -> Text
B.toLazyText (Builder
prefixRDF forall a. Monoid a => a -> a -> a
`mappend` Builder
b)
in case Text -> Maybe QName -> ParseResult
parseN3 Text
t forall a. Maybe a
Nothing of
Left String
msg -> forall a. HasCallStack => String -> a
error String
msg
Right RDFGraph
gr -> RDFGraph
gr
makeRDFFormula ::
Namespace
-> LName
-> B.Builder
-> RDFFormula
makeRDFFormula :: Namespace -> LName -> Builder -> Formula RDFGraph
makeRDFFormula Namespace
scope LName
local Builder
gr =
Formula
{ formName :: ScopedName
formName = Namespace -> LName -> ScopedName
makeNSScopedName Namespace
scope LName
local
, formExpr :: RDFGraph
formExpr = Builder -> RDFGraph
makeRDFGraphFromN3Builder Builder
gr
}
makeRDFClosureRule ::
ScopedName
-> [RDFGraph]
-> RDFGraph
-> RDFVarBindingModify
-> RDFRule
makeRDFClosureRule :: ScopedName
-> [RDFGraph] -> RDFGraph -> RDFVarBindingModify -> Rule RDFGraph
makeRDFClosureRule ScopedName
sname [RDFGraph]
antgrs RDFGraph
congr RDFVarBindingModify
vmod = GraphClosure RDFLabel -> Rule RDFGraph
makeGraphClosureRule
GraphClosure
{ nameGraphRule :: ScopedName
nameGraphRule = ScopedName
sname
, ruleAnt :: RDFArcSet
ruleAnt = forall (f :: * -> *) a. (Foldable f, Ord a) => f (Set a) -> Set a
S.unions forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map forall (lg :: * -> *) lb. LDGraph lg lb => lg lb -> ArcSet lb
getArcs [RDFGraph]
antgrs
, ruleCon :: RDFArcSet
ruleCon = forall (lg :: * -> *) lb. LDGraph lg lb => lg lb -> ArcSet lb
getArcs RDFGraph
congr
, ruleModify :: RDFVarBindingModify
ruleModify = RDFVarBindingModify
vmod
}
makeN3ClosureRule ::
Namespace
-> LName
-> B.Builder
-> B.Builder
-> RDFVarBindingModify
-> RDFRule
makeN3ClosureRule :: Namespace
-> LName
-> Builder
-> Builder
-> RDFVarBindingModify
-> Rule RDFGraph
makeN3ClosureRule Namespace
scope LName
local Builder
ant Builder
con =
ScopedName
-> [RDFGraph] -> RDFGraph -> RDFVarBindingModify -> Rule RDFGraph
makeRDFClosureRule (Namespace -> LName -> ScopedName
makeNSScopedName Namespace
scope LName
local) [RDFGraph
antgr] RDFGraph
congr
where
antgr :: RDFGraph
antgr = Builder -> RDFGraph
makeRDFGraphFromN3Builder Builder
ant
congr :: RDFGraph
congr = Builder -> RDFGraph
makeRDFGraphFromN3Builder Builder
con
makeN3ClosureSimpleRule ::
Namespace
-> LName
-> B.Builder
-> B.Builder
-> RDFRule
makeN3ClosureSimpleRule :: Namespace -> LName -> Builder -> Builder -> Rule RDFGraph
makeN3ClosureSimpleRule Namespace
scope LName
local Builder
ant Builder
con =
Namespace
-> LName
-> Builder
-> Builder
-> RDFVarBindingModify
-> Rule RDFGraph
makeN3ClosureRule Namespace
scope LName
local Builder
ant Builder
con forall a b. VarBindingModify a b
varBindingId
makeN3ClosureModifyRule ::
Namespace
-> LName
-> B.Builder
-> B.Builder
-> RDFVarBindingModify
-> RDFVarBindingModify
-> RDFRule
makeN3ClosureModifyRule :: Namespace
-> LName
-> Builder
-> Builder
-> RDFVarBindingModify
-> RDFVarBindingModify
-> Rule RDFGraph
makeN3ClosureModifyRule Namespace
scope LName
local Builder
ant Builder
con RDFVarBindingModify
vflt RDFVarBindingModify
vmod =
Namespace
-> LName
-> Builder
-> Builder
-> RDFVarBindingModify
-> Rule RDFGraph
makeN3ClosureRule Namespace
scope LName
local Builder
ant Builder
con RDFVarBindingModify
modc
where
modc :: RDFVarBindingModify
modc = forall a. a -> Maybe a -> a
fromMaybe forall a b. VarBindingModify a b
varBindingId forall a b. (a -> b) -> a -> b
$ forall a b.
Eq a =>
VarBindingModify a b
-> VarBindingModify a b -> Maybe (VarBindingModify a b)
vbmCompose RDFVarBindingModify
vmod RDFVarBindingModify
vflt
makeN3ClosureAllocatorRule ::
Namespace
-> LName
-> B.Builder
-> B.Builder
-> RDFVarBindingModify
-> ( [RDFLabel] -> RDFVarBindingModify )
-> RDFRule
makeN3ClosureAllocatorRule :: Namespace
-> LName
-> Builder
-> Builder
-> RDFVarBindingModify
-> ([RDFLabel] -> RDFVarBindingModify)
-> Rule RDFGraph
makeN3ClosureAllocatorRule Namespace
scope LName
local Builder
ant Builder
con RDFVarBindingModify
vflt [RDFLabel] -> RDFVarBindingModify
aloc =
ScopedName
-> [RDFGraph] -> RDFGraph -> RDFVarBindingModify -> Rule RDFGraph
makeRDFClosureRule (Namespace -> LName -> ScopedName
makeNSScopedName Namespace
scope LName
local) [RDFGraph
antgr] RDFGraph
congr RDFVarBindingModify
modc
where
antgr :: RDFGraph
antgr = Builder -> RDFGraph
makeRDFGraphFromN3Builder Builder
ant
congr :: RDFGraph
congr = Builder -> RDFGraph
makeRDFGraphFromN3Builder Builder
con
vmod :: RDFVarBindingModify
vmod = [RDFLabel] -> RDFVarBindingModify
aloc forall a b. (a -> b) -> a -> b
$ forall a. Set a -> [a]
S.toList (forall lb. Label lb => (lb -> Bool) -> NSGraph lb -> Set lb
allLabels forall lb. Label lb => lb -> Bool
labelIsVar RDFGraph
antgr)
modc :: RDFVarBindingModify
modc = forall a. a -> Maybe a -> a
fromMaybe forall a b. VarBindingModify a b
varBindingId forall a b. (a -> b) -> a -> b
$ forall a b.
Eq a =>
VarBindingModify a b
-> VarBindingModify a b -> Maybe (VarBindingModify a b)
vbmCompose RDFVarBindingModify
vmod RDFVarBindingModify
vflt
makeNodeAllocTo ::
RDFLabel
-> RDFLabel
-> [RDFLabel]
-> RDFVarBindingModify
makeNodeAllocTo :: RDFLabel -> RDFLabel -> [RDFLabel] -> RDFVarBindingModify
makeNodeAllocTo RDFLabel
bindvar RDFLabel
alocvar [RDFLabel]
exbnode = VarBindingModify
{ vbmName :: ScopedName
vbmName = LName -> ScopedName
swishName LName
"makeNodeAllocTo"
, vbmApply :: [RDFVarBinding] -> [RDFVarBinding]
vbmApply = RDFLabel
-> RDFLabel -> [RDFLabel] -> [RDFVarBinding] -> [RDFVarBinding]
applyNodeAllocTo RDFLabel
bindvar RDFLabel
alocvar [RDFLabel]
exbnode
, vbmVocab :: [RDFLabel]
vbmVocab = [RDFLabel
alocvar,RDFLabel
bindvar]
, vbmUsage :: [[RDFLabel]]
vbmUsage = [[RDFLabel
bindvar]]
}
applyNodeAllocTo ::
RDFLabel -> RDFLabel -> [RDFLabel] -> [RDFVarBinding] -> [RDFVarBinding]
applyNodeAllocTo :: RDFLabel
-> RDFLabel -> [RDFLabel] -> [RDFVarBinding] -> [RDFVarBinding]
applyNodeAllocTo RDFLabel
bindvar RDFLabel
alocvar [RDFLabel]
exbnode [RDFVarBinding]
vars =
let
app :: VarBinding a a -> a -> a
app = forall a. VarBinding a a -> a -> a
applyVarBinding
alocnodes :: [(RDFLabel, RDFLabel)]
alocnodes = forall a b. [a] -> [b] -> [(a, b)]
zip (forall a. Eq a => [a] -> [a]
nub forall a b. (a -> b) -> a -> b
$ forall a b. [a -> b] -> a -> [b]
flist (forall a b. (a -> b) -> [a] -> [b]
map forall a. VarBinding a a -> a -> a
app [RDFVarBinding]
vars) RDFLabel
alocvar)
(forall lb. Label lb => lb -> [lb] -> [lb]
newNodes (RDFLabel -> RDFLabel
makeBlank RDFLabel
bindvar) [RDFLabel]
exbnode)
newvb :: RDFVarBinding -> RDFVarBinding
newvb RDFVarBinding
var = forall a b.
(Ord a, Ord b) =>
VarBinding a b -> VarBinding a b -> VarBinding a b
joinVarBindings
( forall a b. (Ord a, Ord b) => [(a, b)] -> VarBinding a b
makeVarBinding forall a b. (a -> b) -> a -> b
$ forall a. [a] -> a
head
[ [(RDFLabel
bindvar,RDFLabel
b)] | (RDFLabel
v,RDFLabel
b) <- [(RDFLabel, RDFLabel)]
alocnodes, forall a. VarBinding a a -> a -> a
app RDFVarBinding
var RDFLabel
alocvar forall a. Eq a => a -> a -> Bool
== RDFLabel
v ] )
RDFVarBinding
var
in
forall a b. (a -> b) -> [a] -> [b]
map RDFVarBinding -> RDFVarBinding
newvb [RDFVarBinding]
vars