1. Mark Evenson
  2. jeannie

Commits

Mark Evenson  committed ee7dafa Merge

Automated merge with ssh://not.org/work/jeannie

  • Participants
  • Parent commits 40a8b38, 484974e
  • Branches default

Comments (0)

Files changed (8)

File README.markdown

File contents unchanged.

File jeannie.asd

File contents unchanged.

File packages.lisp

View file
   (:use :cl :abcl-asdf)
   (:documentation "http://en.wikipedia.org/wiki/I_Dream_of_Jeannie")
   (:nicknames :jena)
-  (:export #:index))
+  (:import-from :jss :new)
+  (:export 
+   #:read-rdf 
+   
+   #:*model*
 
-(in-package :jeannie)
+   #:list-namesaces #:list-objects #:list-subjects #:list-statements
 
-(defun index () 
-  "Return the index of locally cached Jena jars that will be used"
-  ;;; TODO use these libraries in the ASDF definition.
-  (abcl-asdf:resolve-dependencies "org.apache.jena" "jena-arq"))
+   #:index))
+

File src/index.lisp

View file
+(in-package :jeannie)
+
+(defun index () 
+  "Return the index of locally cached Jena jars that will be used"
+  ;;; TODO use these libraries in the ASDF definition.
+  (abcl-asdf:resolve-dependencies "org.apache.jena" "jena-arq"))

File src/java.lisp

View file
+(in-package :jeannie)
+
+;;; From abcld 
+
+(defvar *verbose* nil
+  "When set, *VERBOSE* indicates the stream to log verbose messages to.")
+
+;;; c.f. http://nklein.com/2011/04/delayed-evaluation-across-packages/
+;;;
+;;; The question is whether creating a closure is generally cheaper
+;;; than evaluating arguments to FORMAT?
+(defmacro verbose (message &rest parameters)
+  `(when *verbose*
+     (format *verbose* (funcall (lambda() (format nil ,message ,@parameters))))
+     (finish-output *verbose*)))
+
+(defun jstream (file)
+  "For a pathname named in FILE, return a Java java.io.InputStreamReader"
+  (handler-case
+      (let* ((pathname (namestring (merge-pathnames file)))
+	     (file-input-stream (jss:new 'FileInputStream pathname))
+	     (input-stream-reader (jss:new 'InputStreamReader
+						file-input-stream)))
+	(verbose "Opened '~A' for read." file)
+	input-stream-reader)
+    ;;; XXX Fix java exception hierarchy
+    (java-throwable (e)
+	(error "Failed to load file '~S' because of throwable: ~A"
+	       file e))
+    (java-exception (e)
+	(error "Failed to load file '~S' because of exception: ~A"
+	       file e))))

File src/jena.lisp

View file
+(in-package :jeannie)
+
+(defparameter *model* nil)
+
+;;; FIXME define as generic function
+(defun read-rdf (filename)
+  "Reads the contents of FILENAME as n3 triples. 
+
+As a side-effect, the special variable JEANNIE:*MODEL* is set to the
+result of this call."
+
+  (unless *model*
+    (setf *model* (#"createDefaultModel" 'ModelFactory)))
+  (with-open-file (s filename :direction :input)
+    (let* ((lang "N3")
+           (base "https://jena.not.org/index#rdf")
+
+           (reader (#"getReader" *model* lang))
+           (input-stream (jstream s)))
+      (#"read" reader *model* input-stream base)))
+  *model*)
+
+
+;;; introspect a Model
+
+;;; (let ((i (#"listObjects" *model*)) ) (values (#"next" i) (#"next" i) (#"next" i) ))  --> com.hp.hpl.jena.rdf.model.impl.ResourceImpl
+
+;; implement me!
+;; (defmacro jiterator-to-list (get-iterator model)
+;;     (mapcar #"toString" (loop :with iterator = (#"listStatements" *model*) :while (#"hasNext" iterator) :collect (#"next" iterator)))
+
+(defun list-statements (&optional (model *model*))
+    (mapcar #"toString" 
+            (loop 
+               :with iterator = (#"listStatements" *model*) 
+               :while (#"hasNext" iterator)
+               :collect (#"next" iterator))))
+
+(defun list-objects (&optional (model *model*))
+    (mapcar #"toString" 
+            (loop 
+               :with iterator = (#"listObjects" *model*) 
+               :while (#"hasNext" iterator)
+               :collect (#"next" iterator))))
+
+(defun list-namespaces (&optional (model *model*))
+    (mapcar #"toString" 
+            (loop 
+               :with iterator = (#"listNameSpaces" *model*) 
+               :while (#"hasNext" iterator)
+               :collect (#"next" iterator))))
+
+(defun list-subjects (&optional (model *model*))
+    (mapcar #"toString" 
+            (loop 
+               :with iterator = (#"listSubjects" *model*) 
+               :while (#"hasNext" iterator)
+               :collect (#"next" iterator))))
+
+

File test/tests.lisp

View file
+(in-package :jeannie)
+(rt:deftest jeannie.read-rdf.1
+    (#"toString"
+     (read-rdf (asdf:system-relative-pathname :jeannie "test/tests.n3")))
+  t)
+
+;;; XXX needs to have run JEANNIE.READ-RDF.1 to initialize *MODEL*
+(rt:deftest jeannie.model.1
+    (mapcar #"toString" (loop :with iterator = (#"listObjects" *model*) :while (#"hasNext" iterator) :collect (#"next" iterator)))
+  t)
+
+    

File test/tests.n3

View file
+# N.B. totally bogus wrt n3 semantics, but it does parse...
+@prefix :  <urn:common-lisp:package:keyword> .
+@prefix jeannie: <https://bitbucket.org/easye/jeannie#index.not.org> .
+
+@prefix dc:      <http://purl.org/dc/terms/> .
+@prefix rdf:     <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+
+@prefix rt:      <http://evenson.not.org/quicklisp/rt#> .
+@prefix asdf:    <http://abcl.org/require/asdf#> .
+
+_:0 rdf:first rt:do-tests ;
+    dc:label "The null prototype of the first test." .
+
+<test/users/evenson/1> 
+  rdf:first (jeannie:read-rdf (asdf:system-relative-pathname :jeannie "test/tests.n3")) .
+