activesesame 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,92 @@
1
+ class ActiveSesame::OwlThing
2
+ require 'digest/sha1'
3
+ include ActiveSesame::Support
4
+ #class methods for building the definition of the class
5
+ # - The most basic definition should (when inheriting from OwlThing create the subClassOf triple
6
+ # - The init method is the same for all even owl thing
7
+ #init for creating a new instance of the thing
8
+ # - A method to create a uri for the thing
9
+ # - - This could be <blank> as well
10
+
11
+ # OwlThing.new creates a new term that is a rdf:type of owl:Thing
12
+ # when a class is created that inherits from OwlThing the definition for the class term is yet another instantiation of owl thing that can be placed in a class attribute
13
+ # new results in rdf:type relationship, inherited results in rdfs:subClassOf relationship
14
+
15
+ # Use class attribute term as the place for keeping
16
+ # Pass in the uri and object through the new() when inherited as called
17
+ # Questions to be answered:
18
+ # -Does self.add_triple/term.add_relationships overwrite relationships or always add to unsaved_triples?
19
+
20
+
21
+ # TODO:
22
+ # -Be sure that if the term exists that it will populate relationships and what not appropriately
23
+ # -Be sure the "unsaved triples" are not added when the triple already exists
24
+ # -Add find methods:
25
+ # --Find for uri (id equivalent)
26
+ # --find(:all)
27
+ # --find(:all/:first, :conditions => "?self rdf:type #{self.class.term.term} . user input" (made with sparql query object?)
28
+
29
+ class << self
30
+ attr_accessor :repository, :term, :uri
31
+ end
32
+
33
+ attr_accessor :uri, :term
34
+
35
+ def self.inherited(klass)
36
+ klass.term.add_triple({:subject => "base:#{klass}", :predicate => "rdfs:subClassOf", :object => "owl:Thing"})
37
+ end
38
+
39
+ def self.repository
40
+ @repository ||= self.repository = ActiveSesame::Repository.new #Setting default repository
41
+ end
42
+
43
+ def self.set_repository(repo)
44
+ self.repository = repo
45
+ self.reset_term
46
+ end
47
+
48
+ def self.uri
49
+ @uri ||= "base:" + self.to_s.split("::").last
50
+ end
51
+
52
+ def self.set_uri(uri)
53
+ self.uri = uri
54
+ self.reset_term
55
+ end
56
+
57
+ def self.term
58
+ @term ||= ActiveSesame::Ontology::Term.new(uri, self.repository)
59
+ end
60
+
61
+ def self.reset_term
62
+ @term = ActiveSesame::Ontology::Term.new(uri, self.repository)
63
+ @term.add_triple({:subject => "base:#{self}", :predicate => "rdfs:subClassOf", :object => "owl:Thing"})
64
+ end
65
+
66
+
67
+ def self.method_missing(method, *args, &block)
68
+ self.term.send(method, *args, &block)
69
+ end
70
+
71
+ def method_missing(method, *args, &block)
72
+ self.term.send(method, *args, &block)
73
+ end
74
+
75
+ def initialize(options={})
76
+ @uri = options[:uri] if options[:uri]
77
+ @uri ||= self.generate_uri
78
+ @term = ActiveSesame::Ontology::Term.new(@uri, self.class.repository)
79
+ self.add_triple({:subject => @uri, :predicate => "rdf:type", :object => self.class.uri}) if @term.relationships.size == 0
80
+ end
81
+
82
+ def repository
83
+ self.class.repository
84
+ end
85
+
86
+ def generate_uri
87
+ self.repository.base_uri + "#" + Digest::SHA1.hexdigest(Time.now.to_s + self.object_id.to_s)
88
+ end
89
+
90
+ @uri = "owl:Thing" #Set the default URI to the correct owl term
91
+
92
+ end
@@ -0,0 +1,46 @@
1
+ module ActiveSesame
2
+ #
3
+ # The represenation and means of exploring RDF Classes
4
+ #
5
+ class RDFClass
6
+
7
+ attr_reader :name, :properties, :subclasses, :superclass
8
+
9
+ def self.find(klass, options={})
10
+ @@connection ||= Repository.new
11
+ class_types.inject([]) {|memo, type| ResultParser.singular_values(@@connection.find_by_sparql("SELECT ?klass WHERE { ?klass rdf:type #{type} }")) }
12
+ end
13
+
14
+ def self.class_types
15
+ ["rdf:Class", "owl:Class", "owl:Thing"]
16
+ end
17
+
18
+ def initialize(name)
19
+ self.name = name
20
+ self.properties = find_properties
21
+ self.sublcasses = find_subclasses
22
+ self.superclass = find_superclass
23
+ end
24
+
25
+ def find_properties
26
+ ResultParser.singular_values(@@connection.find_by_sparql("SELECT ?property WHERE { #{self.name} rdf:property ?property }"))
27
+ end
28
+
29
+ def find_subclasses
30
+ ResultParser.singular_values(@@connection.find_by_sparql("SELECT ?subClasses WHERE { #{self.name} rdf:subClassOf ?subClasses }"))
31
+ end
32
+
33
+ def find_superclass
34
+ ResultParser.singular_values(@@connection.find_by_sparql("SELECT ?super WHERE { ?super rdfs:subClassOf #{self.name} }"))
35
+ end
36
+
37
+ def add_triple(*args)
38
+ if args.size == 3
39
+ Repository.save_triple(args[0], args[1], args[3])
40
+ elsif args.size == 1 and (args[0].class == Triple or args[0].class == Hash)
41
+ Repository.save_triple(args[0][:subject], args[0][:predicate], args[0][:object])
42
+ end
43
+ end
44
+ end
45
+ end
46
+
@@ -0,0 +1,55 @@
1
+ module ActiveSesame::RDFConstants
2
+ def self.literal_to_proc_hash
3
+ {
4
+ "http://www.w3.org/2001/XMLSchema#string" => :to_s,
5
+ "http://www.w3.org/2001/XMLSchema#dateTime" => :to_time,
6
+ "http://www.w3.org/2001/XMLSchema#int" => :to_i
7
+ }
8
+ end
9
+
10
+ def self.literals
11
+ [
12
+ "http://www.w3.org/2001/XMLSchema#string",
13
+ "http://www.w3.org/2001/XMLSchema#int",
14
+ "http://www.w3.org/2001/XMLSchema#dateTime",
15
+ ]
16
+ end
17
+
18
+ def self.class_to_match_hash
19
+ {
20
+ String => "xsd:string",
21
+ Time => "xsd:dateTime",
22
+ Date => "xsd:date",
23
+ Fixnum => "xsd:integer"
24
+ }
25
+ end
26
+
27
+ def self.class_to_literal
28
+ {
29
+ String => "http://www.w3.org/2001/XMLSchema#string",
30
+ Time => "http://www.w3.org/2001/XMLSchema#dateTime",
31
+ Date => "http://www.w3.org/2001/XMLSchema#date",
32
+ Fixnum => "http://www.w3.org/2001/XMLSchema#int"
33
+ }
34
+ end
35
+
36
+ def self.prefixes
37
+ {
38
+ :xsd => "http://www.w3.org/2001/XMLSchema",
39
+ :owl => "http://www.w3.org/2002/07/owl",
40
+ :rdf => "http://www.w3.org/1999/02/22-rdf-syntax-ns",
41
+ :rdfs => "http://www.w3.org/2000/01/rdf-schema",
42
+ }
43
+ end
44
+
45
+ def self.uri_to_prefix(uri, additional_uris={})
46
+ uri_prefix, term = uri.split("#","")
47
+ uri_prefixes = self.prefixes.merge(additional_uris)
48
+ if term and uri_prefixes.has_key?(uri_without_pound)
49
+ uri_prefixes[uri_without_pound] + ":" + term
50
+ else
51
+ uri
52
+ end
53
+ end
54
+ end
55
+
@@ -0,0 +1,7 @@
1
+ module ActiveSesame
2
+ #
3
+ # The represenation and means of exploring RDF properties
4
+ #
5
+ class RDFProperty
6
+ end
7
+ end
@@ -0,0 +1,103 @@
1
+ module ActiveSesame
2
+ class Repository
3
+
4
+ @@prefixes = {"xsd" => "http://www.w3.org/2001/XMLSchema#",
5
+ "ss" => "http://study-stash.radiology.umm.edu/ontologies/study-stash.owl",
6
+ "owl" => "http://www.w3.org/2002/07/owl",
7
+ "rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns",
8
+ "rdfs" => "http://www.w3.org/2000/01/rdf-schema"}
9
+
10
+ attr_accessor :triple_store_id, :repository_uri, :repository_location, :base_uri, :connector, :prefixes
11
+
12
+ def initialize(repository_type=SesameProtocol, options={})
13
+ self.send(:extend, repository_type)
14
+ options = default_options.merge(options)
15
+ options.each {|key,value| send("#{key}=".to_sym, value) if respond_to?(key) }
16
+ self.prefixes = @@prefixes
17
+ end
18
+
19
+ def find_by_sparql(query, include_prefixes=true)
20
+ query_dispatch("", :method => :get, :body => {:query => self.sparql_base + " " + self.prefixes_to_sparql + " " + query, :queryLn => "SPARQL"})
21
+ end
22
+
23
+ def find(query, include_prefixes=true)
24
+ ActiveSesame::ResultParser.tableize(find_by_sparql(query, include_prefixes))
25
+ end
26
+
27
+ def group_save(xml)
28
+ query_dispatch("statements", {:method => :post, "content-type" => "application/x-rdftransaction", :body => xml})
29
+ end
30
+
31
+ def save_triple(subject, predicate, object)
32
+ query_dispatch("statements", {:method => :put, :body => {:subj => subject, :pred => predicate, :obj => object}})
33
+ end
34
+
35
+ def delete_by_pattern(subject, predicate, object)
36
+ query_dispatch("statements", {:method => :delete, :body => {:subj => subject, :pred => predicate, :obj => object}})
37
+ end
38
+
39
+ def add_prefix(prefix, uri)
40
+ self.prefixes = self.prefixes.merge({prefix => uri})
41
+ end
42
+
43
+ def add_prefixes(prefix_hash)
44
+ self.prefixes = self.prefixes.merge(prefix_hash)
45
+ end
46
+
47
+ def sparql_base
48
+ "BASE <#{base_uri}>"
49
+ end
50
+
51
+ def prefixes_to_sparql
52
+ self.prefixes.keys.inject("") {|sparql,key| sparql += "PREFIX #{key}: <#{self.prefixes[key]}> " }
53
+ end
54
+
55
+ end
56
+
57
+ module SesameProtocol
58
+ require 'rest-open-uri'
59
+ require 'uri'
60
+
61
+ def self.extended(klass)
62
+ simple_rest_methods :size, :contexts, :namespaces
63
+ end
64
+
65
+ def query_dispatch(method_name, args={})
66
+ args[:body][:query] = encode_sparql(args[:body][:query]) if args[:body][:query] if args[:body]
67
+ args[:body][:subj] = encode_sparql(args[:body][:subj]) if args[:body][:subj] if args[:body]
68
+ args[:body][:pred] = encode_sparql(args[:body][:pred]) if args[:body][:pred] if args[:body]
69
+ args[:body][:obj] = encode_sparql(args[:body][:obj]) if args[:body][:obj] if args[:body]
70
+ [:get, :put, :delete].include?(args[:method]) ? vars_if_get = hash_to_get(args[:body]) : vars_if_get = ""
71
+ method_name == "" ? slash = "" : slash = "/"
72
+ return open(self.repository_uri + "/" + self.triple_store_id + slash + method_name.to_s + vars_if_get, args).read
73
+ end
74
+
75
+ def self.simple_rest_methods(*method_names)
76
+ method_names.each do |name|
77
+ new_name = name.to_s
78
+ define_method(new_name) { return query_dispatch(name) }
79
+ end
80
+ end
81
+
82
+ private
83
+ def encode_sparql(query)
84
+ URI.encode(query).gsub("?","%3f").gsub("/","%2f").gsub(":","%3a").gsub("\\","5C")
85
+ end
86
+
87
+ def hash_to_get(hash)
88
+ (hash.inject("?") {|total,tuple| total += "#{tuple[0]}=#{tuple[1]}&"}).chop
89
+ end
90
+
91
+ def default_options
92
+ {
93
+ :repository_uri => "http://localhost:8111/sesame/repositories",
94
+ :triple_store_id => "test",
95
+ :location => "http://localhost:8111/sesame/repositories/test",
96
+ :query_language => "SPARQL",
97
+ :base_uri => "http://www.fakeontology.org/ontology.owl"
98
+ }
99
+ end
100
+
101
+ end
102
+
103
+ end
@@ -0,0 +1,67 @@
1
+ module ActiveSesame
2
+ module ResultParser
3
+ require 'libxml'
4
+ #def ResultParser.append_features(someClass)
5
+ def self.tableize(xml_document)
6
+ xml_document = self.to_document(xml_document)
7
+ rows = []
8
+ xml_document.find("/sparql/results/result").each do |result|
9
+ hash = {}
10
+ result.each_element do |binding|
11
+ key = binding.attributes.to_h["name"]
12
+ hash[key] = value_from_binding(binding)
13
+ end
14
+ rows << hash
15
+ end
16
+ return rows
17
+ end
18
+
19
+ def self.singular_values(xml_document)
20
+ xml_document = self.to_document(xml_document)
21
+ values = []
22
+ xml_document.find("/sparql/results/result/binding").each {|binding| values << self.value_from_binding(binding) }
23
+ return values
24
+ end
25
+
26
+ def self.hash_values(xml_document)
27
+ xml_document = REXML::Document.new(xml_document) if xml_document.class == String
28
+ keys = []
29
+ xml_document.elements.each("/sparql/head/variable") do |variable|
30
+ keys << variable.attributes["name"]
31
+ end
32
+ xml_document = REXML::Document.new(xml_document) if xml_document.class == String
33
+ hash = {}
34
+ xml_document.elements.each("/sparql/results/result") do |result|
35
+ hash[result.elements["binding[@name='#{keys[0]}']/uri|literal"].text] = result.elements["binding[@name='#{keys[1]}']/uri|literal"].text
36
+ end
37
+ return hash
38
+ end
39
+
40
+ def self.value_from_binding(binding)
41
+ literal = binding.find_first("literal")
42
+ uri = binding.find_first("uri")
43
+ if uri
44
+ uri.content
45
+ elsif literal
46
+ type_cast_literal(literal)
47
+ end
48
+ end
49
+
50
+ def self.type_cast_literal(literal_element)
51
+ #puts literal_element.attributes["datatype"] #Use when Exception thrown "nil is not a Symbol"
52
+ return literal_element.content.send(RDFConstants.literal_to_proc_hash[literal_element.attributes.to_h["datatype"]]) if literal_element.attributes.to_h["datatype"]
53
+ return literal_element.text
54
+ end
55
+ #end
56
+
57
+ private
58
+ def self.to_document(string_or_doc)
59
+ if string_or_doc.class == String
60
+ string_or_doc.sub!("xmlns=\"http://www.w3.org/2005/sparql-results#\"","")
61
+ LibXML::XML::Document.string(string_or_doc)
62
+ else
63
+ string_or_doc
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,114 @@
1
+ module ActiveSesame
2
+ module Support
3
+
4
+ #Think about changing to a uri class rather than manipulating strings...
5
+ def self.property_to_constant(prop)
6
+ prop = prop.to_s
7
+ prop = ResultParser.uri_to_sym(prop) if prop.match(/#/)
8
+ prop.first.upcase + prop.slice(1,prop.length)
9
+ end
10
+
11
+ def self.uri_to_sym(uri)
12
+ uri.split("#")[1].to_sym
13
+ end
14
+
15
+ def self.encode_whitespace(string)
16
+ string.gsub(" ","%20")
17
+ end
18
+
19
+ def self.uncode_whitespace(string)
20
+ return string.class == String ? string.gsub("%20"," ") : string
21
+ end
22
+
23
+ def is_uri?(string)
24
+ if string.class == String
25
+ string =~ /^http:\/\//
26
+ else
27
+ false
28
+ end
29
+ end
30
+
31
+ def uri_to_prefix(uri, additional_uris={})
32
+ uri_prefix, term = uri.split("#")
33
+ uri_prefixes = ActiveSesame::RDFConstants.prefixes.merge(additional_uris)
34
+ uri_prefixes = uri_prefixes.keys.inject(Hash.new) {|hash,key| hash[uri_prefixes[key]] = key; hash} #reverse key and value
35
+ #puts "\n" + uri_prefixes.inspect + "\n"
36
+ if uri_prefixes.has_key?(uri_prefix)
37
+ uri_prefixes[uri_prefix]
38
+ else
39
+ uri_prefix
40
+ end
41
+ end
42
+
43
+ def method_from_uri(uri, additional_uris={})
44
+ #puts "uris for doober: #{additional_uris.inspect}"
45
+ #puts "uri to be transformed to method #{uri}"
46
+ #puts "method generated: #{self.uri_to_prefix(uri, additional_uris)}"
47
+ uri_prefix = self.uri_to_prefix(uri, additional_uris)
48
+ bogus, term = uri.split("#")
49
+ term ? "#{uri_prefix}_#{term}" : uri_prefix
50
+ end
51
+
52
+ def expand_triples(triple_list, additional_uris={})
53
+ #puts "\n#{additional_uris.inspect}\n"
54
+ triple_list.collect {|triple| expand_triple(triple, additional_uris) }
55
+ end
56
+
57
+ def expand_triple(triple, additional_uris={})
58
+ #puts "\n#{additional_uris.inspect}\n"
59
+ triple.keys.inject(Hash.new) {|hash,key| hash[key] = expand_term(triple[key], additional_uris); hash }
60
+ end
61
+
62
+ def expand_terms(term_list, additional_uris={})
63
+ #puts "\n#{additional_uris.inspect}\n"
64
+ term_list.collect {|term| self.expand_term(term) }
65
+ end
66
+
67
+ def expand_term(full_term, additional_uris={})
68
+ #puts "\n#{additional_uris.inspect}\n"
69
+ prefix, term = full_term.split(":")
70
+ (term != nil and not is_uri?(full_term)) ? expand_prefix(prefix, additional_uris) + "#" + term : full_term
71
+ end
72
+
73
+ def expand_prefix(prefix, additional_uris={})
74
+ #puts "\n#{additional_uris.inspect}\n"
75
+ if additional_uris.has_key?(prefix)
76
+ additional_uris[prefix]
77
+ else
78
+ throw "Invalid Prefix: the prefix \"#{prefix}\" was not found in #{additional_uris.inspect}"
79
+ end
80
+ end
81
+
82
+ end
83
+
84
+ class Triple
85
+ attr_accessor :hash
86
+
87
+ def self.triple_components
88
+ [:subject, :object, :predicate]
89
+ end
90
+
91
+ def method_missing(method, *args, &block)
92
+ if self.hash.has_key?(method)
93
+ self.hash[method]
94
+ else
95
+ super(method, *args, &block)
96
+ end
97
+ end
98
+
99
+ def initialize(real_hash={})
100
+ self.hash = real_hash.keys.inject(Hash.new) {|hash,key| hash[key.to_sym] = real_hash[key] if self.class.triple_components.include?(key.to_sym); hash }
101
+ unless self.hash.has_key?(:subject) and self.hash.has_key?(:object) and self.hash.has_key?(:predicate)
102
+ raise "Not a valid triple: missing subject, object, or predicate"
103
+ end
104
+ end
105
+
106
+ def to_hash
107
+ self.hash
108
+ end
109
+
110
+ def to_triple
111
+ self
112
+ end
113
+ end
114
+ end