(in-package #:db.agraph.user)

#| Example 1

Show RDFS++ reasoning operating across 7 triples spread over
three triple-stores.

|#

(defun setup-federated-reasoning-example-1 ()
  (close-all-triple-stores)
  (register-namespace "ex" "http://www.franz.com/simple#" 
		      :errorp nil)

  ;; create the stores
  (create-triple-store "a")
  (create-triple-store "b")
  (create-triple-store "c")

  ;; add triples
  (with-triple-store (db "a")
    (add-triple !ex:SmallBlackDog !rdfs:subClassOf !ex:BlackDog)
    (add-triple !ex:BlackDog !rdfs:subClassOf !ex:Dog)
    (add-triple !ex:Dog !rdfs:subClassOf !ex:Mammal))
  (with-triple-store (db "b")
    (add-triple !ex:Giraffe !rdfs:subClassOf !ex:Mammal)
    (add-triple !ex:Lion !rdfs:subClassOf !ex:Mammal))
  (with-triple-store (db "c")
    (add-triple !ex:Mammal !rdfs:subClassOf !ex:Animal)
    (add-triple !ex:Abbey !rdf:type !ex:BlackDog))

  ;; federate them
  (federate-triple-stores "fed" (list "a" "b" "c"))
  (setf *db* (apply-rdfs++-reasoner :db (find-triple-store "fed"))))

(defun test-federated-reasoning-example-1 ()
  (dolist (class (list !ex:SmallBlackDog
		       !ex:BlackDog
		       !ex:Dog
		       !ex:Mammal
		       !ex:Animal))
    (format t "~&Abbey is~:[ not~;~] a ~a.~%"
	    (get-triple :s !ex:Abbey :p !rdf:type :o class)
	    class)))

#|
(setup-federated-reasoning-example-1)
=> #<reasoning-triple-store
     inner #<federated-triple-store fed 3 sub-stores @ #x1298638a> @
     #x1298ecba>

(test-federated-reasoning-example-1)
Abbey is not a !<http://www.franz.com/simple#SmallBlackDog>.
Abbey is a !<http://www.franz.com/simple#BlackDog>.
Abbey is a !<http://www.franz.com/simple#Dog>.
Abbey is a !<http://www.franz.com/simple#Mammal>.
Abbey is a !<http://www.franz.com/simple#Animal>.

(print-triples *db*)
<triple 1: ex:SmallBlackDog rdfs:subClassOf ex:BlackDog default-graph>
<triple 2: ex:BlackDog rdfs:subClassOf ex:Dog default-graph>
<triple 3: ex:Dog rdfs:subClassOf ex:Mammal default-graph>
<triple 1: ex:Giraffe rdfs:subClassOf ex:Mammal default-graph>
<triple 2: ex:Lion rdfs:subClassOf ex:Mammal default-graph>
<triple 1: ex:Mammal rdfs:subClassOf ex:Animal default-graph>
<triple 2: ex:Abbey rdf:type ex:BlackDog default-graph>
<triple 0: ex:Abbey rdf:type ex:Dog default-graph>
<triple 0: ex:Abbey rdf:type ex:Mammal default-graph>
<triple 0: ex:Abbey rdf:type ex:Animal default-graph>
<triple 0: ex:Dog rdfs:subClassOf ex:Animal default-graph>
<triple 0: ex:BlackDog rdfs:subClassOf ex:Animal default-graph>
<triple 0: ex:BlackDog rdfs:subClassOf ex:Mammal default-graph>
<triple 0: ex:SmallBlackDog rdfs:subClassOf ex:Animal default-graph>
<triple 0: ex:SmallBlackDog rdfs:subClassOf ex:Mammal default-graph>
<triple 0: ex:SmallBlackDog rdfs:subClassOf ex:Dog default-graph>
<triple 0: ex:Giraffe rdfs:subClassOf ex:Animal default-graph>
<triple 0: ex:Lion rdfs:subClassOf ex:Animal default-graph>


(select (?o)
  (q- !ex:Abbey !rdf:type ?o))
=> (("http://www.franz.com/simple#BlackDog"))

(select (?o)
  (q !ex:Abbey !rdf:type ?o))
=> (("http://www.franz.com/simple#Dog")
    ("http://www.franz.com/simple#Mammal")
    ("http://www.franz.com/simple#Animal")
    ("http://www.franz.com/simple#BlackDog"))

(sparql:run-sparql "
PREFIX ex: <http://www.franz.com/simple#> 
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?o {
  ex:Abbey rdf:type ?o .
}" :results-format :table)
-------------------
| o               |
===================
| ex:BlackDog     |
| ex:Dog          |
| ex:Mammal       |
| ex:Animal       |
-------------------

|#

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Part two : LUBM and federation

(defun open-lubm-datasets (root partition-count)
  (let ((files (directory (string+ (namestring root)
				   (string+ "lubm-50-*-of-" partition-count)))))
    (unless files
      (error "No lubm datasets found in ~a" root))
    (let ((stores 
	   (loop for file in files collect
		(open-triple-store 
		 (subseq 
		  (namestring file) 0 (length (namestring file)))))))
      (setf *db* (federate-triple-stores "lubm-fed" stores))
      (apply-rdfs++-reasoner))))

(defmacro defquery (name &body body)
  `(compile (defun ,name () ,@body)))

(defun register-lubm-namespaces (lubm-uri)
  (register-namespace "ub" lubm-uri :errorp nil)
  (register-namespace "rdf" "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
  (register-namespace "rdfs" "http://www.w3.org/2000/01/rdf-schema#"))

(defun create-lubm-namespaces (university-count)
  (dotimes (i university-count)
    (dotimes (j 40)
      (register-namespace
       (format nil "u~ad~a" i j)
       (format nil "http://www.Department~a.University~a.edu/" j i)))))

(defun lubm-setup ()
  (create-lubm-namespaces 50)
  (register-lubm-namespaces 
   "http://www.lehigh.edu/%7Ezhp2/2004/0401/univ-bench.owl#")
  t)

(defquery q1
    (select (?x)
	    (q ?x !ub:takesCourse !u0d0:GraduateCourse0)
	    (q ?x !rdf:type !ub:GraduateStudent)))

(defquery q1b
    (select (?x)
	    (q- ?x !ub:takesCourse !u0d0:GraduateCourse0)
	    (q- ?x !rdf:type !ub:GraduateStudent)))

(defquery q4
    (select (?x ?name ?email ?telephone)	
	    (q ?x !ub:worksFor !<http://www.Department0.University0.edu>)
	    (q ?x !rdf:type !ub:Professor)
	    (q ?x !ub:name ?name)
	    (q ?x !ub:emailAddress ?email)
	    (q ?x !ub:telephone ?telephone)))

#|

(lubm-setup)
=> t

(open-lubm-datasets "/x/gwking/triple-stores/lubm-50-federation/"
                      6)
#<reasoning-triple-store
  inner #<federated-triple-store lubm-fed 6 sub-stores @ #x1004f8dce2>
  @ #x1004f8e1b2>

(q1)
(("http://www.Department0.University0.edu/GraduateStudent124")
 ("http://www.Department0.University0.edu/GraduateStudent44")
 ("http://www.Department0.University0.edu/GraduateStudent142")
 ("http://www.Department0.University0.edu/GraduateStudent101"))

(q1b)
(("http://www.Department0.University0.edu/GraduateStudent124")
 ("http://www.Department0.University0.edu/GraduateStudent44")
 ("http://www.Department0.University0.edu/GraduateStudent142")
 ("http://www.Department0.University0.edu/GraduateStudent101"))

(q4)
(("http://www.Department0.University0.edu/FullProfessor7"
  "FullProfessor7" "FullProfessor7@Department0.University0.edu"
  "xxx-xxx-xxxx")
 ("http://www.Department0.University0.edu/AssociateProfessor5"
  "AssociateProfessor5"
  "AssociateProfessor5@Department0.University0.edu" "xxx-xxx-xxxx")
 ("http://www.Department0.University0.edu/AssociateProfessor4"
  "AssociateProfessor4"
  "AssociateProfessor4@Department0.University0.edu" "xxx-xxx-xxxx")
 ("http://www.Department0.University0.edu/AssociateProfessor2"
  "AssociateProfessor2"
  "AssociateProfessor2@Department0.University0.edu" "xxx-xxx-xxxx")
 ("http://www.Department0.University0.edu/AssistantProfessor1"
  "AssistantProfessor1"
  "AssistantProfessor1@Department0.University0.edu" "xxx-xxx-xxxx")
 ("http://www.Department0.University0.edu/AssociateProfessor6"
  "AssociateProfessor6"
  "AssociateProfessor6@Department0.University0.edu" "xxx-xxx-xxxx")
 ("http://www.Department0.University0.edu/AssistantProfessor7"
  "AssistantProfessor7"
  "AssistantProfessor7@Department0.University0.edu" "xxx-xxx-xxxx")
 ("http://www.Department0.University0.edu/AssociateProfessor7"
  "AssociateProfessor7"
  "AssociateProfessor7@Department0.University0.edu" "xxx-xxx-xxxx")
 ("http://www.Department0.University0.edu/AssociateProfessor3"
  "AssociateProfessor3"
  "AssociateProfessor3@Department0.University0.edu" "xxx-xxx-xxxx")
 ("http://www.Department0.University0.edu/AssistantProfessor9"
  "AssistantProfessor9"
  "AssistantProfessor9@Department0.University0.edu" "xxx-xxx-xxxx")
 ...)

;;; now try with just part of the store
(setf *db* (find-triple-store "lubm-50-2-of-6"))
#<db.agraph::triple-db
  /x/gwking/triple-stores/lubm-50-federation/lubm-50-2-of-6, open @
  #x10023ebe32>

(apply-rdfs++-reasoner)
#<reasoning-triple-store
  inner #<triple-db
          /x/gwking/triple-stores/lubm-50-federation/lubm-50-2-of-6, open
          @ #x10023ebe32>
  @ #x10043aeae2>

(q4)
=> nil

|#