rdf 1.1.3 → 1.1.4
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.
- checksums.yaml +4 -4
- data/CREDITS +1 -0
- data/VERSION +1 -1
- data/lib/rdf.rb +10 -48
- data/lib/rdf/cli/vocab-loader.rb +78 -142
- data/lib/rdf/mixin/enumerable.rb +25 -0
- data/lib/rdf/mixin/mutable.rb +3 -0
- data/lib/rdf/model/graph.rb +1 -1
- data/lib/rdf/model/node.rb +25 -2
- data/lib/rdf/model/statement.rb +20 -12
- data/lib/rdf/model/uri.rb +11 -2
- data/lib/rdf/nquads.rb +8 -6
- data/lib/rdf/ntriples/writer.rb +14 -10
- data/lib/rdf/query/pattern.rb +10 -8
- data/lib/rdf/reader.rb +11 -2
- data/lib/rdf/repository.rb +1 -1
- data/lib/rdf/vocab.rb +396 -96
- data/lib/rdf/vocab/cc.rb +117 -25
- data/lib/rdf/vocab/cert.rb +230 -117
- data/lib/rdf/vocab/dc.rb +930 -233
- data/lib/rdf/vocab/dc11.rb +151 -37
- data/lib/rdf/vocab/doap.rb +326 -114
- data/lib/rdf/vocab/exif.rb +930 -533
- data/lib/rdf/vocab/foaf.rb +602 -346
- data/lib/rdf/vocab/geo.rb +139 -33
- data/lib/rdf/vocab/gr.rb +1551 -1084
- data/lib/rdf/vocab/ht.rb +319 -0
- data/lib/rdf/vocab/ical.rb +507 -349
- data/lib/rdf/vocab/ma.rb +504 -280
- data/lib/rdf/vocab/mo.rb +2425 -876
- data/lib/rdf/vocab/og.rb +178 -90
- data/lib/rdf/vocab/owl.rb +513 -219
- data/lib/rdf/vocab/prov.rb +1557 -479
- data/lib/rdf/vocab/rdfs.rb +107 -31
- data/lib/rdf/vocab/rdfv.rb +165 -0
- data/lib/rdf/vocab/rsa.rb +61 -18
- data/lib/rdf/vocab/rss.rb +55 -22
- data/lib/rdf/vocab/schema.rb +8590 -3995
- data/lib/rdf/vocab/sioc.rb +657 -218
- data/lib/rdf/vocab/skos.rb +227 -134
- data/lib/rdf/vocab/skosxl.rb +47 -33
- data/lib/rdf/vocab/vcard.rb +693 -327
- data/lib/rdf/vocab/void.rb +175 -132
- data/lib/rdf/vocab/vs.rb +27 -0
- data/lib/rdf/vocab/wdrs.rb +123 -119
- data/lib/rdf/vocab/wot.rb +155 -45
- data/lib/rdf/vocab/xhtml.rb +2 -1
- data/lib/rdf/vocab/xhv.rb +496 -231
- data/lib/rdf/vocab/xsd.rb +382 -53
- data/lib/rdf/writer.rb +8 -4
- metadata +5 -4
- data/lib/rdf/vocab/http.rb +0 -84
- data/lib/rdf/vocab/v.rb +0 -154
data/lib/rdf/model/statement.rb
CHANGED
@@ -6,19 +6,25 @@ module RDF
|
|
6
6
|
# s = RDF::URI.new("http://rubygems.org/gems/rdf")
|
7
7
|
# p = RDF::DC.creator
|
8
8
|
# o = RDF::URI.new("http://ar.to/#self")
|
9
|
-
# RDF::Statement
|
9
|
+
# RDF::Statement(s, p, o)
|
10
10
|
#
|
11
11
|
# @example Creating an RDF statement with a context
|
12
12
|
# uri = RDF::URI("http://example/")
|
13
|
-
# RDF::Statement
|
13
|
+
# RDF::Statement(s, p, o, :context => uri)
|
14
14
|
#
|
15
15
|
# @example Creating an RDF statement from a `Hash`
|
16
|
-
# RDF::Statement
|
16
|
+
# RDF::Statement({
|
17
17
|
# :subject => RDF::URI.new("http://rubygems.org/gems/rdf"),
|
18
18
|
# :predicate => RDF::DC.creator,
|
19
19
|
# :object => RDF::URI.new("http://ar.to/#self"),
|
20
20
|
# })
|
21
21
|
#
|
22
|
+
# @example Creating an RDF statement with interned nodes
|
23
|
+
# RDF::Statement(:s, p, :o)
|
24
|
+
#
|
25
|
+
# @example Creating an RDF statement with a string
|
26
|
+
# RDF::Statement(s, p, "o")
|
27
|
+
#
|
22
28
|
class Statement
|
23
29
|
include RDF::Value
|
24
30
|
|
@@ -54,21 +60,23 @@ module RDF
|
|
54
60
|
##
|
55
61
|
# @overload initialize(options = {})
|
56
62
|
# @param [Hash{Symbol => Object}] options
|
57
|
-
# @option options [RDF::
|
63
|
+
# @option options [RDF::Term] :subject (nil)
|
64
|
+
# A symbol is converted to an interned {Node}.
|
58
65
|
# @option options [RDF::URI] :predicate (nil)
|
59
|
-
# @option options [RDF::
|
60
|
-
# if not
|
61
|
-
# @option options [RDF::
|
62
|
-
# Note, in RDF 1.1, a context MUST be an
|
66
|
+
# @option options [RDF::Resource] :object (nil)
|
67
|
+
# if not a {Resource}, it is coerced to {Literal} or {Node} depending on if it is a symbol or something other than a {Term}.
|
68
|
+
# @option options [RDF::Term] :context (nil)
|
69
|
+
# Note, in RDF 1.1, a context MUST be an {Resource}.
|
63
70
|
# @return [RDF::Statement]
|
64
71
|
#
|
65
72
|
# @overload initialize(subject, predicate, object, options = {})
|
66
|
-
# @param [RDF::
|
73
|
+
# @param [RDF::Term] subject
|
74
|
+
# A symbol is converted to an interned {Node}.
|
67
75
|
# @param [RDF::URI] predicate
|
68
|
-
# @param [RDF::
|
69
|
-
# if not
|
76
|
+
# @param [RDF::Resource] object
|
77
|
+
# if not a {Resource}, it is coerced to {Literal} or {Node} depending on if it is a symbol or something other than a {Term}.
|
70
78
|
# @param [Hash{Symbol => Object}] options
|
71
|
-
# @option options [RDF::
|
79
|
+
# @option options [RDF::Term] :context (nil)
|
72
80
|
# @return [RDF::Statement]
|
73
81
|
def initialize(subject = nil, predicate = nil, object = nil, options = {})
|
74
82
|
case subject
|
data/lib/rdf/model/uri.rb
CHANGED
@@ -140,8 +140,9 @@ module RDF
|
|
140
140
|
#
|
141
141
|
# @param (see #initialize)
|
142
142
|
# @return [RDF::URI] an immutable, frozen URI object
|
143
|
-
def self.intern(
|
144
|
-
|
143
|
+
def self.intern(*args)
|
144
|
+
str = args.first
|
145
|
+
(cache[str = str.to_s] ||= self.new(*args)).freeze
|
145
146
|
end
|
146
147
|
|
147
148
|
##
|
@@ -632,6 +633,14 @@ module RDF
|
|
632
633
|
return nil # no QName found
|
633
634
|
end
|
634
635
|
|
636
|
+
##
|
637
|
+
# Returns a string version of the QName or the full IRI
|
638
|
+
#
|
639
|
+
# @return [String] or `nil`
|
640
|
+
def pname
|
641
|
+
(q = self.qname) ? q.join(":") : to_s
|
642
|
+
end
|
643
|
+
|
635
644
|
##
|
636
645
|
# Returns a duplicate copy of `self`.
|
637
646
|
#
|
data/lib/rdf/nquads.rb
CHANGED
@@ -114,17 +114,18 @@ module RDF
|
|
114
114
|
# @param [RDF::Term] object
|
115
115
|
# @return [void]
|
116
116
|
def write_quad(subject, predicate, object, context)
|
117
|
-
puts format_quad(subject, predicate, object, context)
|
117
|
+
puts format_quad(subject, predicate, object, context, @options)
|
118
118
|
end
|
119
119
|
|
120
120
|
##
|
121
121
|
# Returns the N-Quads representation of a statement.
|
122
122
|
#
|
123
123
|
# @param [RDF::Statement] statement
|
124
|
+
# @param [Hash{Symbol => Object}] options = ({})
|
124
125
|
# @return [String]
|
125
126
|
# @since 0.4.0
|
126
|
-
def format_statement(statement)
|
127
|
-
format_quad(*statement.to_quad)
|
127
|
+
def format_statement(statement, options = {})
|
128
|
+
format_quad(*statement.to_quad, options)
|
128
129
|
end
|
129
130
|
|
130
131
|
##
|
@@ -134,10 +135,11 @@ module RDF
|
|
134
135
|
# @param [RDF::URI] predicate
|
135
136
|
# @param [RDF::Term] object
|
136
137
|
# @param [RDF::Term] context
|
138
|
+
# @param [Hash{Symbol => Object}] options = ({})
|
137
139
|
# @return [String]
|
138
|
-
def format_quad(subject, predicate, object, context)
|
139
|
-
s = "%s %s %s " % [subject, predicate, object].map { |value| format_term(value) }
|
140
|
-
s += format_term(context) + " " if context
|
140
|
+
def format_quad(subject, predicate, object, context, options = {})
|
141
|
+
s = "%s %s %s " % [subject, predicate, object].map { |value| format_term(value, options) }
|
142
|
+
s += format_term(context, options) + " " if context
|
141
143
|
s + "."
|
142
144
|
end
|
143
145
|
end # Writer
|
data/lib/rdf/ntriples/writer.rb
CHANGED
@@ -179,7 +179,7 @@ module RDF::NTriples
|
|
179
179
|
#
|
180
180
|
# @param [IO, File] output
|
181
181
|
# the output stream
|
182
|
-
# @param [Hash{Symbol => Object}] options
|
182
|
+
# @param [Hash{Symbol => Object}] options = ({})
|
183
183
|
# any additional options. See {RDF::Writer#initialize}
|
184
184
|
# @option options [Boolean] :validate (true)
|
185
185
|
# whether to validate terms when serializing
|
@@ -208,16 +208,17 @@ module RDF::NTriples
|
|
208
208
|
# @param [RDF::Term] object
|
209
209
|
# @return [void]
|
210
210
|
def write_triple(subject, predicate, object)
|
211
|
-
puts format_triple(subject, predicate, object)
|
211
|
+
puts format_triple(subject, predicate, object, @options)
|
212
212
|
end
|
213
213
|
|
214
214
|
##
|
215
215
|
# Returns the N-Triples representation of a statement.
|
216
216
|
#
|
217
217
|
# @param [RDF::Statement] statement
|
218
|
+
# @param [Hash{Symbol => Object}] options = ({})
|
218
219
|
# @return [String]
|
219
|
-
def format_statement(statement)
|
220
|
-
format_triple(*statement.to_triple)
|
220
|
+
def format_statement(statement, options = {})
|
221
|
+
format_triple(*statement.to_triple, options)
|
221
222
|
end
|
222
223
|
|
223
224
|
##
|
@@ -226,26 +227,29 @@ module RDF::NTriples
|
|
226
227
|
# @param [RDF::Resource] subject
|
227
228
|
# @param [RDF::URI] predicate
|
228
229
|
# @param [RDF::Term] object
|
230
|
+
# @param [Hash{Symbol => Object}] options = ({})
|
229
231
|
# @return [String]
|
230
|
-
def format_triple(subject, predicate, object)
|
231
|
-
"%s %s %s ." % [subject, predicate, object].map { |value| format_term(value) }
|
232
|
+
def format_triple(subject, predicate, object, options = {})
|
233
|
+
"%s %s %s ." % [subject, predicate, object].map { |value| format_term(value, options) }
|
232
234
|
end
|
233
235
|
|
234
236
|
##
|
235
237
|
# Returns the N-Triples representation of a blank node.
|
236
238
|
#
|
237
239
|
# @param [RDF::Node] node
|
238
|
-
# @param [Hash{Symbol => Object}] options
|
240
|
+
# @param [Hash{Symbol => Object}] options = ({})
|
241
|
+
# @option options [Boolean] :unique_bnodes (false)
|
242
|
+
# Serialize node using unique identifier, rather than any used to create the node.
|
239
243
|
# @return [String]
|
240
244
|
def format_node(node, options = {})
|
241
|
-
node.to_base
|
245
|
+
options[:unique_bnodes] ? node.to_unique_base : node.to_base
|
242
246
|
end
|
243
247
|
|
244
248
|
##
|
245
249
|
# Returns the N-Triples representation of a URI reference.
|
246
250
|
#
|
247
251
|
# @param [RDF::URI] uri
|
248
|
-
# @param [Hash{Symbol => Object}] options
|
252
|
+
# @param [Hash{Symbol => Object}] options = ({})
|
249
253
|
# @return [String]
|
250
254
|
def format_uri(uri, options = {})
|
251
255
|
uri.to_base
|
@@ -255,7 +259,7 @@ module RDF::NTriples
|
|
255
259
|
# Returns the N-Triples representation of a literal.
|
256
260
|
#
|
257
261
|
# @param [RDF::Literal, String, #to_s] literal
|
258
|
-
# @param [Hash{Symbol => Object}] options
|
262
|
+
# @param [Hash{Symbol => Object}] options = ({})
|
259
263
|
# @return [String]
|
260
264
|
def format_literal(literal, options = {})
|
261
265
|
case literal
|
data/lib/rdf/query/pattern.rb
CHANGED
@@ -18,21 +18,23 @@ module RDF; class Query
|
|
18
18
|
##
|
19
19
|
# @overload initialize(options = {})
|
20
20
|
# @param [Hash{Symbol => Object}] options
|
21
|
-
# @option options [Variable, Resource, nil] :subject (nil)
|
22
|
-
# @option options [Variable, URI, nil] :predicate (nil)
|
23
|
-
# @option options [Variable, Term, nil] :object (nil)
|
24
|
-
# @option options [Variable, Resource, nil, false] :context (nil)
|
21
|
+
# @option options [Variable, Resource, Symbol, nil] :subject (nil)
|
22
|
+
# @option options [Variable, URI, Symbol, nil] :predicate (nil)
|
23
|
+
# @option options [Variable, Term, Symbol, nil] :object (nil)
|
24
|
+
# @option options [Variable, Resource, Symbol, nil, false] :context (nil)
|
25
25
|
# A context of nil matches any context, a context of false, matches only the default context.
|
26
26
|
# @option options [Boolean] :optional (false)
|
27
27
|
#
|
28
28
|
# @overload initialize(subject, predicate, object, options = {})
|
29
|
-
# @param [Variable, Resource, nil] subject
|
30
|
-
# @param [Variable, URI, nil] predicate
|
31
|
-
# @param [Variable, Termm, nil] object
|
29
|
+
# @param [Variable, Resource, Symbol, nil] subject
|
30
|
+
# @param [Variable, URI, Symbol, nil] predicate
|
31
|
+
# @param [Variable, Termm, Symbol, nil] object
|
32
32
|
# @param [Hash{Symbol => Object}] options
|
33
|
-
# @option options [Variable, Resource, nil, false] :context (nil)
|
33
|
+
# @option options [Variable, Resource, Symbol, nil, false] :context (nil)
|
34
34
|
# A context of nil matches any context, a context of false, matches only the default context.
|
35
35
|
# @option options [Boolean] :optional (false)
|
36
|
+
#
|
37
|
+
# @note {Statement} treats symbols as interned {Node} instances, in a {Pattern}, they are treated as {Variable}.
|
36
38
|
def initialize(subject = nil, predicate = nil, object = nil, options = {})
|
37
39
|
super
|
38
40
|
end
|
data/lib/rdf/reader.rb
CHANGED
@@ -115,9 +115,18 @@ module RDF
|
|
115
115
|
##
|
116
116
|
# Parses input from the given file name or URL.
|
117
117
|
#
|
118
|
+
# @note A reader returned via this method may not be readable depending on the processing model of the specific reader, as the file is only open during the scope of `open`. The reader is intended to be accessed through a block.
|
119
|
+
#
|
120
|
+
# @example Parsing RDF statements from a file
|
121
|
+
# RDF::Reader.open("etc/doap.nt") do |reader|
|
122
|
+
# reader.each_statement do |statement|
|
123
|
+
# puts statement.inspect
|
124
|
+
# end
|
125
|
+
# end
|
126
|
+
#
|
118
127
|
# @param [String, #to_s] filename
|
119
128
|
# @param [Hash{Symbol => Object}] options
|
120
|
-
# any additional options (see {RDF::Reader#initialize} and {RDF::Format.for})
|
129
|
+
# any additional options (see {RDF::Util::File.open_file}, {RDF::Reader#initialize} and {RDF::Format.for})
|
121
130
|
# @option options [Symbol] :format (:ntriples)
|
122
131
|
# @yield [reader]
|
123
132
|
# @yieldparam [RDF::Reader] reader
|
@@ -138,7 +147,7 @@ module RDF
|
|
138
147
|
if reader
|
139
148
|
reader.new(file, options, &block)
|
140
149
|
else
|
141
|
-
raise FormatError, "unknown RDF format: #{format_options.inspect}"
|
150
|
+
raise FormatError, "unknown RDF format: #{format_options.inspect}\nThis may be resolved with a require of the 'linkeddata' gem."
|
142
151
|
end
|
143
152
|
end
|
144
153
|
end
|
data/lib/rdf/repository.rb
CHANGED
@@ -71,7 +71,7 @@ module RDF
|
|
71
71
|
#
|
72
72
|
# @param [String, Array<String>] filenames
|
73
73
|
# @param [Hash{Symbol => Object}] options
|
74
|
-
# Options from {RDF::
|
74
|
+
# Options from {RDF::Repository#initialize} and {RDF::Mutable#load}
|
75
75
|
# @yield [repository]
|
76
76
|
# @yieldparam [Repository]
|
77
77
|
# @return [void]
|
data/lib/rdf/vocab.rb
CHANGED
@@ -2,6 +2,11 @@ module RDF
|
|
2
2
|
##
|
3
3
|
# A {Vocabulary} represents an RDFS or OWL vocabulary.
|
4
4
|
#
|
5
|
+
# A {Vocabulary} can also serve as a Domain Specific Language (DSL) for generating an RDF Graph definition for the vocabulary (see {RDF::Vocabulary#to_graph}).
|
6
|
+
#
|
7
|
+
# ### Defining a vocabulary using the DSL
|
8
|
+
# Vocabularies can be defined based on {RDF::Vocabulary} or {RDF::StrictVocabulary} using a simple Domain Specific Language (DSL). Terms of the vocabulary are specified using either `property` or `term` (alias), with the attributes of the term listed in a hash. See {property} for description of the hash.
|
9
|
+
#
|
5
10
|
# ### Vocabularies:
|
6
11
|
#
|
7
12
|
# The following vocabularies are pre-defined for your convenience:
|
@@ -16,7 +21,7 @@ module RDF
|
|
16
21
|
# * {RDF::FOAF} - Friend of a Friend (FOAF)
|
17
22
|
# * {RDF::GEO} - WGS84 Geo Positioning (GEO)
|
18
23
|
# * {RDF::GR} - Good Relations
|
19
|
-
# * {RDF::
|
24
|
+
# * {RDF::HT} - Hypertext Transfer Protocol (HTTP)
|
20
25
|
# * {RDF::ICAL} - iCal
|
21
26
|
# * {RDF::MA} - W3C Meda Annotations
|
22
27
|
# * {RDF::OG} - FaceBook OpenGraph
|
@@ -55,6 +60,19 @@ module RDF
|
|
55
60
|
# foaf[:name] #=> RDF::URI("http://xmlns.com/foaf/0.1/name")
|
56
61
|
# foaf['mbox'] #=> RDF::URI("http://xmlns.com/foaf/0.1/mbox")
|
57
62
|
#
|
63
|
+
# @example Generating RDF from a vocabulary definition
|
64
|
+
# graph = RDF::RDFS.to_graph
|
65
|
+
# graph.dump(:ntriples)
|
66
|
+
#
|
67
|
+
# @example Defining a simple vocabulary
|
68
|
+
# class EX < RDF::StrictVocabulay("http://example/ns#")
|
69
|
+
# term :Class,
|
70
|
+
# label: "My Class",
|
71
|
+
# comment: "Good to use as an example",
|
72
|
+
# "rdf:type" => "rdfs:Class",
|
73
|
+
# "rdfs:subClassOf" => "http://example/SuperClass"
|
74
|
+
# end
|
75
|
+
#
|
58
76
|
# @see http://www.w3.org/TR/curie/
|
59
77
|
# @see http://en.wikipedia.org/wiki/QName
|
60
78
|
class Vocabulary
|
@@ -73,56 +91,125 @@ module RDF
|
|
73
91
|
# Ruby's autoloading facility, meaning that `@@subclasses` will be
|
74
92
|
# empty until each subclass has been touched or require'd.
|
75
93
|
RDF::VOCABS.each { |v| require "rdf/vocab/#{v}" unless v == :rdf }
|
76
|
-
@@subclasses.each(&block)
|
94
|
+
@@subclasses.select(&:name).each(&block)
|
77
95
|
else
|
78
|
-
|
96
|
+
__properties__.each(&block)
|
79
97
|
end
|
80
98
|
end
|
81
99
|
|
100
|
+
##
|
101
|
+
# Is this a strict vocabulary, or a liberal vocabulary allowing arbitrary properties?
|
102
|
+
def strict?; false; end
|
103
|
+
|
82
104
|
##
|
83
105
|
# @overload property
|
84
106
|
# Returns `property` in the current vocabulary
|
85
|
-
# @return [RDF::
|
107
|
+
# @return [RDF::Vocabulary::Term]
|
86
108
|
#
|
87
109
|
# @overload property(name, options)
|
88
110
|
# Defines a new property or class in the vocabulary.
|
89
|
-
# Optional labels and comments are stripped of unnecessary whitespace.
|
90
111
|
#
|
91
112
|
# @param [String, #to_s] name
|
92
113
|
# @param [Hash{Symbol => Object}] options
|
93
|
-
#
|
94
|
-
# @option options [String,
|
114
|
+
# Any other values are expected to be String which expands to a {URI} using built-in vocabulary prefixes. The value is a `String` or `Array<String>` which is interpreted according to the `range` of the associated property.
|
115
|
+
# @option options [String, Array<String>] :label
|
116
|
+
# Shortcut for `rdfs:label`, values are String interpreted as a {Literal}.
|
117
|
+
# @option options [String, Array<String>] :comment
|
118
|
+
# Shortcut for `rdfs:comment`, values are String interpreted as a {Literal}.
|
119
|
+
# @option options [String, Array<String>] :subClassOf
|
120
|
+
# Shortcut for `rdfs:subClassOf`, values are String interpreted as a {URI}.
|
121
|
+
# @option options [String, Array<String>] :subPropertyOf
|
122
|
+
# Shortcut for `rdfs:subPropertyOf`, values are String interpreted as a {URI}.
|
123
|
+
# @option options [String, Array<String>] :domain
|
124
|
+
# Shortcut for `rdfs:domain`, values are String interpreted as a {URI}.
|
125
|
+
# @option options [String, Array<String>] :range
|
126
|
+
# Shortcut for `rdfs:range`, values are String interpreted as a {URI}.
|
127
|
+
# @option options [String, Array<String>] :type
|
128
|
+
# Shortcut for `rdf:type`, values are String interpreted as a {URI}.
|
129
|
+
# @return [RDF::Vocabulary::Term]
|
95
130
|
def property(*args)
|
96
131
|
case args.length
|
97
132
|
when 0
|
98
|
-
|
133
|
+
Term.intern("#{self}property", attributes: {label: "property", vocab: self})
|
99
134
|
else
|
100
135
|
name, options = args
|
101
|
-
options
|
102
|
-
prop =
|
103
|
-
|
104
|
-
@@comments[prop] = options[:comment].to_s.strip.gsub(/\s+/m, ' ') if options[:comment]
|
136
|
+
options = {:label => name.to_s, vocab: self}.merge(options || {})
|
137
|
+
prop = Term.intern([to_s, name.to_s].join(''), attributes: options)
|
138
|
+
props[prop] = options
|
105
139
|
(class << self; self; end).send(:define_method, name) { prop } unless name.to_s == "property"
|
140
|
+
prop
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Alternate use for vocabulary terms, functionally equivalent to {#property}.
|
145
|
+
alias_method :term, :property
|
146
|
+
alias_method :__property__, :property
|
147
|
+
|
148
|
+
##
|
149
|
+
# @return [Array<RDF::URI>] a list of properties in the current vocabulary
|
150
|
+
def properties
|
151
|
+
props.keys
|
152
|
+
end
|
153
|
+
alias_method :__properties__, :properties
|
154
|
+
|
155
|
+
##
|
156
|
+
# Attempt to expand a Compact IRI/PName/QName using loaded vocabularies
|
157
|
+
#
|
158
|
+
# @param [String, #to_s] pname
|
159
|
+
# @return [RDF::URI]
|
160
|
+
def expand_pname(pname)
|
161
|
+
prefix, suffix = pname.to_s.split(":", 2)
|
162
|
+
if prefix == "rdf"
|
163
|
+
RDF[suffix]
|
164
|
+
elsif vocab = RDF::Vocabulary.each.detect {|v| v.__name__ && v.__prefix__ == prefix.to_sym}
|
165
|
+
suffix.to_s.empty? ? vocab.to_uri : vocab[suffix]
|
166
|
+
else
|
167
|
+
RDF::Vocabulary.find_term(pname) || RDF::URI(pname)
|
106
168
|
end
|
107
169
|
end
|
108
170
|
|
171
|
+
##
|
172
|
+
# Return the Vocabulary associated with a URI
|
173
|
+
#
|
174
|
+
# @param [RDF::URI] uri
|
175
|
+
# @return [Vocabulary]
|
176
|
+
def find(uri)
|
177
|
+
RDF::Vocabulary.detect {|v| RDF::URI(uri).start_with?(v.to_uri)}
|
178
|
+
end
|
179
|
+
|
180
|
+
##
|
181
|
+
# Return the Vocabulary term associated with a URI
|
182
|
+
#
|
183
|
+
# @param [RDF::URI] uri
|
184
|
+
# @return [Vocabulary::Term]
|
185
|
+
def find_term(uri)
|
186
|
+
uri = RDF::URI(uri)
|
187
|
+
return uri if uri.is_a?(Vocabulary::Term)
|
188
|
+
vocab = RDF::Vocabulary.detect {|v| uri.start_with?(v.to_uri)}
|
189
|
+
term = vocab[uri.to_s[vocab.to_uri.to_s.length..-1]] if vocab
|
190
|
+
end
|
191
|
+
|
109
192
|
##
|
110
193
|
# Returns the URI for the term `property` in this vocabulary.
|
111
194
|
#
|
112
195
|
# @param [#to_s] property
|
113
196
|
# @return [RDF::URI]
|
114
197
|
def [](property)
|
115
|
-
|
198
|
+
if self.respond_to?(property.to_sym)
|
199
|
+
self.send(property.to_sym)
|
200
|
+
else
|
201
|
+
Term.intern([to_s, property.to_s].join(''), attributes: {vocab: self})
|
202
|
+
end
|
116
203
|
end
|
117
204
|
|
118
205
|
# @return [String] The label for the named property
|
119
206
|
def label_for(name)
|
120
|
-
|
207
|
+
props.fetch(self[name], {}).fetch(:label, "")
|
121
208
|
end
|
122
209
|
|
123
210
|
# @return [String] The comment for the named property
|
124
211
|
def comment_for(name)
|
125
|
-
|
212
|
+
props.fetch(self[name], {}).fetch(:comment, "")
|
126
213
|
end
|
127
214
|
|
128
215
|
##
|
@@ -133,6 +220,65 @@ module RDF
|
|
133
220
|
RDF::URI.intern(to_s)
|
134
221
|
end
|
135
222
|
|
223
|
+
# For IRI compatibility
|
224
|
+
alias_method :to_iri, :to_uri
|
225
|
+
|
226
|
+
##
|
227
|
+
# Return an enumerator over {RDF::Statement} defined for this vocabulary.
|
228
|
+
# @return [RDF::Enumerable::Enumerator]
|
229
|
+
# @see Object#enum_for
|
230
|
+
def enum_for(method = :each_statement, *args)
|
231
|
+
# Ensure that enumerators are, themselves, queryable
|
232
|
+
this = self
|
233
|
+
Enumerable::Enumerator.new do |yielder|
|
234
|
+
this.send(method, *args) {|*y| yielder << (y.length > 1 ? y : y.first)}
|
235
|
+
end
|
236
|
+
end
|
237
|
+
alias_method :to_enum, :enum_for
|
238
|
+
|
239
|
+
##
|
240
|
+
# Enumerate each statement constructed from the defined vocabulary terms
|
241
|
+
#
|
242
|
+
# If a property value is known to be a {URI}, or expands to a {URI}, the `object` is a URI, otherwise, it will be a {Literal}.
|
243
|
+
#
|
244
|
+
# @yield statement
|
245
|
+
# @yieldparam [RDF::Statement]
|
246
|
+
def each_statement(&block)
|
247
|
+
props.each do |subject, attributes|
|
248
|
+
attributes.each do |prop, values|
|
249
|
+
prop = RDF::Vocabulary.expand_pname(prop) unless prop.is_a?(Symbol)
|
250
|
+
next unless prop
|
251
|
+
Array(values).each do |value|
|
252
|
+
case prop
|
253
|
+
when :type
|
254
|
+
prop = RDF.type
|
255
|
+
value = expand_pname(value)
|
256
|
+
when :subClassOf
|
257
|
+
prop = RDFS.subClassOf
|
258
|
+
value = expand_pname(value)
|
259
|
+
when :subPropertyOf
|
260
|
+
prop = RDFS.subPropertyOf
|
261
|
+
value = expand_pname(value)
|
262
|
+
when :domain
|
263
|
+
prop = RDFS.domain
|
264
|
+
value = expand_pname(value)
|
265
|
+
when :range
|
266
|
+
prop = RDFS.range
|
267
|
+
value = expand_pname(value)
|
268
|
+
when :label
|
269
|
+
prop = RDFS.label
|
270
|
+
when :comment
|
271
|
+
prop = RDFS.comment
|
272
|
+
else
|
273
|
+
value = RDF::Vocabulary.expand_pname(value)
|
274
|
+
end
|
275
|
+
|
276
|
+
block.call RDF::Statement(subject, prop, value)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
136
282
|
##
|
137
283
|
# Returns a string representation of this vocabulary class.
|
138
284
|
#
|
@@ -141,6 +287,71 @@ module RDF
|
|
141
287
|
@@uris.has_key?(self) ? @@uris[self].to_s : super
|
142
288
|
end
|
143
289
|
|
290
|
+
##
|
291
|
+
# Load a vocabulary, optionally from a separate location.
|
292
|
+
#
|
293
|
+
# @param [URI, #to_s] uri
|
294
|
+
# @param [Hash{Symbol => Object}] options
|
295
|
+
# @option options [String] class_name
|
296
|
+
# The class_name associated with the vocabulary, used for creating the class name of the vocabulary. This will create a new class named with a top-level constant based on `class_name`.
|
297
|
+
# @option options [URI, #to_s] :location
|
298
|
+
# Location from which to load the vocabulary, if not from `uri`.
|
299
|
+
# @option options [Array<Symbol>, Hash{Symbol => Hash}] :extra
|
300
|
+
# Extra terms to add to the vocabulary. In the first form, it is an array of symbols, for which terms are created. In the second, it is a Hash mapping symbols to property attributes, as described in {#property}.
|
301
|
+
# @return [RDF::Vocabulary] the loaded vocabulary
|
302
|
+
def load(uri, options = {})
|
303
|
+
source = options.fetch(:location, uri)
|
304
|
+
class_name = options[:class_name]
|
305
|
+
vocab = if class_name
|
306
|
+
Object.const_set(class_name, Class.new(self.create(uri)))
|
307
|
+
else
|
308
|
+
Class.new(self.create(uri))
|
309
|
+
end
|
310
|
+
|
311
|
+
graph = RDF::Graph.load(source)
|
312
|
+
term_defs = {}
|
313
|
+
graph.each do |statement|
|
314
|
+
next unless statement.subject.uri? && statement.subject.start_with?(uri)
|
315
|
+
name = statement.subject.to_s[uri.to_s.length..-1]
|
316
|
+
term = (term_defs[name.to_sym] ||= {})
|
317
|
+
key = case statement.predicate
|
318
|
+
when RDF.type then :type
|
319
|
+
when RDF::RDFS.subClassOf then :subClassOf
|
320
|
+
when RDF::RDFS.subPropertyOf then :subPropertyOf
|
321
|
+
when RDF::RDFS.range then :range
|
322
|
+
when RDF::RDFS.domain then :domain
|
323
|
+
when RDF::RDFS.comment then :comment
|
324
|
+
when RDF::RDFS.label then :label
|
325
|
+
else statement.predicate.pname
|
326
|
+
end
|
327
|
+
|
328
|
+
value = if statement.object.uri?
|
329
|
+
statement.object.pname
|
330
|
+
elsif statement.object.literal? && (statement.object.language || :en) == :en
|
331
|
+
statement.object.to_s
|
332
|
+
end
|
333
|
+
|
334
|
+
(term[key] ||= []) << value if value
|
335
|
+
end
|
336
|
+
|
337
|
+
# Create extra terms
|
338
|
+
term_defs = case options[:extra]
|
339
|
+
when Array
|
340
|
+
options[:extra].inject({}) {|memo, s| memo[s.to_sym] = {label: s.to_s}; memo}.merge(term_defs)
|
341
|
+
when Hash
|
342
|
+
options[:extra].merge(term_defs)
|
343
|
+
else
|
344
|
+
term_defs
|
345
|
+
end
|
346
|
+
|
347
|
+
# Create each term
|
348
|
+
term_defs.each do |term, attributes|
|
349
|
+
vocab.term term, attributes
|
350
|
+
end
|
351
|
+
|
352
|
+
vocab
|
353
|
+
end
|
354
|
+
|
144
355
|
##
|
145
356
|
# Returns a developer-friendly representation of this vocabulary class.
|
146
357
|
#
|
@@ -156,15 +367,39 @@ module RDF
|
|
156
367
|
# Preserve the class name so that it can be obtained even for
|
157
368
|
# vocabularies that define a `name` property:
|
158
369
|
alias_method :__name__, :name
|
159
|
-
end
|
160
370
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
371
|
+
##
|
372
|
+
# Returns a suggested CURIE/PName prefix for this vocabulary class.
|
373
|
+
#
|
374
|
+
# @return [Symbol]
|
375
|
+
# @since 0.3.0
|
376
|
+
def __prefix__
|
377
|
+
__name__.split('::').last.downcase.to_sym
|
378
|
+
end
|
379
|
+
|
380
|
+
protected
|
381
|
+
def inherited(subclass) # @private
|
382
|
+
unless @@uri.nil?
|
383
|
+
@@subclasses << subclass unless %w(http://www.w3.org/1999/02/22-rdf-syntax-ns#).include?(@@uri)
|
384
|
+
subclass.send(:private_class_method, :new)
|
385
|
+
@@uris[subclass] = @@uri
|
386
|
+
@@uri = nil
|
387
|
+
end
|
388
|
+
super
|
389
|
+
end
|
390
|
+
|
391
|
+
def method_missing(property, *args, &block)
|
392
|
+
if %w(to_ary).include?(property.to_s)
|
393
|
+
super
|
394
|
+
elsif args.empty? && !to_s.empty?
|
395
|
+
Term.intern([to_s, property.to_s].join(''), attributes: {vocab: self})
|
396
|
+
else
|
397
|
+
super
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
private
|
402
|
+
def props; @properties ||= {}; end
|
168
403
|
end
|
169
404
|
|
170
405
|
# Undefine all superfluous instance methods:
|
@@ -189,7 +424,7 @@ module RDF
|
|
189
424
|
# @param [#to_s] property
|
190
425
|
# @return [URI]
|
191
426
|
def [](property)
|
192
|
-
|
427
|
+
Term.intern([to_s, property.to_s].join(''), attributes: {vocab: self.class})
|
193
428
|
end
|
194
429
|
|
195
430
|
##
|
@@ -200,6 +435,9 @@ module RDF
|
|
200
435
|
RDF::URI.intern(to_s)
|
201
436
|
end
|
202
437
|
|
438
|
+
# For IRI compatibility
|
439
|
+
alias_method :to_iri, :to_uri
|
440
|
+
|
203
441
|
##
|
204
442
|
# Returns a string representation of this vocabulary.
|
205
443
|
#
|
@@ -223,29 +461,13 @@ module RDF
|
|
223
461
|
self
|
224
462
|
end
|
225
463
|
|
226
|
-
def self.inherited(subclass) # @private
|
227
|
-
@@subclasses << subclass
|
228
|
-
unless @@uri.nil?
|
229
|
-
subclass.send(:private_class_method, :new)
|
230
|
-
@@uris[subclass] = @@uri
|
231
|
-
@@uri = nil
|
232
|
-
end
|
233
|
-
super
|
234
|
-
end
|
235
|
-
|
236
|
-
def self.method_missing(property, *args, &block)
|
237
|
-
if args.empty? && @@uris.has_key?(self)
|
238
|
-
self[property]
|
239
|
-
else
|
240
|
-
super
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
464
|
def method_missing(property, *args, &block)
|
245
|
-
if
|
465
|
+
if %w(to_ary).include?(property.to_s)
|
466
|
+
super
|
467
|
+
elsif args.empty?
|
246
468
|
self[property]
|
247
469
|
else
|
248
|
-
|
470
|
+
super
|
249
471
|
end
|
250
472
|
end
|
251
473
|
|
@@ -254,73 +476,151 @@ module RDF
|
|
254
476
|
@@subclasses = [::RDF] # @private
|
255
477
|
@@uris = {} # @private
|
256
478
|
@@uri = nil # @private
|
257
|
-
@@labels = {}
|
258
|
-
@@comments = {}
|
259
|
-
end # Vocabulary
|
260
479
|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
480
|
+
# A Vocabulary Term is a URI that can also act as an {Enumerable} to generate the RDF definition of vocabulary terms as defined within the vocabulary definition.
|
481
|
+
class Term < RDF::URI
|
482
|
+
# Attributes of this vocabulary term, used for finding `label` and `comment` and to serialize the term back to RDF.
|
483
|
+
# @return [Hash{Symbol,Resource => Term, #to_s}]
|
484
|
+
attr_accessor :attributes
|
485
|
+
|
486
|
+
##
|
487
|
+
# @overload URI(uri, options = {})
|
488
|
+
# @param [URI, String, #to_s] uri
|
489
|
+
# @param [Hash{Symbol => Object}] options
|
490
|
+
# @option options [Boolean] :validate (false)
|
491
|
+
# @option options [Boolean] :canonicalize (false)
|
492
|
+
# @option options [Hash{Symbol,Resource => Term, #to_s}] :attributes
|
493
|
+
# Attributes of this vocabulary term, used for finding `label` and `comment` and to serialize the term back to RDF
|
494
|
+
#
|
495
|
+
# @overload URI(options = {})
|
496
|
+
# @param [Hash{Symbol => Object}] options
|
497
|
+
# @option options [Boolean] :validate (false)
|
498
|
+
# @option options [Boolean] :canonicalize (false)
|
499
|
+
# @option [Vocabulary] :vocab The {Vocabulary} associated with this term.
|
500
|
+
# @option [String, #to_s] :scheme The scheme component.
|
501
|
+
# @option [String, #to_s] :user The user component.
|
502
|
+
# @option [String, #to_s] :password The password component.
|
503
|
+
# @option [String, #to_s] :userinfo
|
504
|
+
# The userinfo component. If this is supplied, the user and password
|
505
|
+
# components must be omitted.
|
506
|
+
# @option [String, #to_s] :host The host component.
|
507
|
+
# @option [String, #to_s] :port The port component.
|
508
|
+
# @option [String, #to_s] :authority
|
509
|
+
# The authority component. If this is supplied, the user, password,
|
510
|
+
# userinfo, host, and port components must be omitted.
|
511
|
+
# @option [String, #to_s] :path The path component.
|
512
|
+
# @option [String, #to_s] :query The query component.
|
513
|
+
# @option [String, #to_s] :fragment The fragment component.
|
514
|
+
# @option options [Hash{Symbol,Resource => Term, #to_s}] :attributes
|
515
|
+
# Attributes of this vocabulary term, used for finding `label` and `comment` and to serialize the term back to RDF
|
516
|
+
def initialize(*args)
|
517
|
+
options = args.last.is_a?(Hash) ? args.last : {}
|
518
|
+
@attributes = options.fetch(:attributes)
|
519
|
+
super
|
274
520
|
end
|
275
521
|
|
276
522
|
##
|
277
|
-
#
|
278
|
-
# Returns `property` in the current vocabulary
|
279
|
-
# @return [RDF::URI]
|
523
|
+
# Vocabulary of this term.
|
280
524
|
#
|
281
|
-
# @
|
282
|
-
|
283
|
-
|
525
|
+
# @return [RDF::Vocabulary]
|
526
|
+
def vocab; @attributes.fetch(:vocab); end
|
527
|
+
|
528
|
+
##
|
529
|
+
# Returns a duplicate copy of `self`.
|
284
530
|
#
|
285
|
-
#
|
286
|
-
|
287
|
-
|
288
|
-
# @option options [String, #to_s] :comment
|
289
|
-
def property(*args)
|
290
|
-
case args.length
|
291
|
-
when 0
|
292
|
-
RDF::URI.intern("#{self}property")
|
293
|
-
else
|
294
|
-
name, options = args
|
295
|
-
options ||= {}
|
296
|
-
prop = RDF::URI.intern([to_s, name.to_s].join(''))
|
297
|
-
@@properties[prop] = true
|
298
|
-
@@labels[prop] = options[:label].to_s.strip.gsub(/\s+/m, ' ') if options[:label]
|
299
|
-
@@comments[prop] = options[:comment].to_s.strip.gsub(/\s+/m, ' ') if options[:comment]
|
300
|
-
(class << self; self; end).send(:define_method, name) { prop } unless name.to_s == "property"
|
301
|
-
end
|
531
|
+
# @return [RDF::URI]
|
532
|
+
def dup
|
533
|
+
self.class.new((@value || @object).dup, attributes: @attributes)
|
302
534
|
end
|
303
535
|
|
304
536
|
##
|
305
|
-
#
|
306
|
-
|
307
|
-
|
537
|
+
# Determine if the URI is a valid according to RFC3987
|
538
|
+
#
|
539
|
+
# @return [Boolean] `true` or `false`
|
540
|
+
# @since 0.3.9
|
541
|
+
def valid?
|
542
|
+
# Validate relative to RFC3987
|
543
|
+
to_s.match(RDF::URI::IRI) || false
|
308
544
|
end
|
309
545
|
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
546
|
+
##
|
547
|
+
# Is this a class term?
|
548
|
+
# @return [Boolean]
|
549
|
+
def class?
|
550
|
+
!!(self.type.to_s =~ /Class/)
|
551
|
+
end
|
552
|
+
|
553
|
+
##
|
554
|
+
# Is this a class term?
|
555
|
+
# @return [Boolean]
|
556
|
+
def property?
|
557
|
+
!!(self.type.to_s =~ /Property/)
|
558
|
+
end
|
559
|
+
|
560
|
+
##
|
561
|
+
# Is this a class term?
|
562
|
+
# @return [Boolean]
|
563
|
+
def datatype?
|
564
|
+
!!(self.type.to_s =~ /Datatype/)
|
565
|
+
end
|
566
|
+
|
567
|
+
##
|
568
|
+
# Is this neither a class, property or datatype term?
|
569
|
+
# @return [Boolean]
|
570
|
+
def other?
|
571
|
+
!!(self.type.to_s !~ /(Class|Property|Datatype)/)
|
572
|
+
end
|
573
|
+
|
574
|
+
##
|
575
|
+
# Returns a <code>String</code> representation of the URI object's state.
|
576
|
+
#
|
577
|
+
# @return [String] The URI object's state, as a <code>String</code>.
|
578
|
+
def inspect
|
579
|
+
sprintf("#<%s:%#0x URI:%s>", Term.to_s, self.object_id, self.to_s)
|
580
|
+
end
|
581
|
+
|
582
|
+
# Implement accessor to symbol attributes
|
583
|
+
def respond_to?(method)
|
584
|
+
@attributes.has_key?(method) || super
|
585
|
+
end
|
586
|
+
|
587
|
+
protected
|
588
|
+
# Implement accessor to symbol attributes
|
589
|
+
def method_missing(method, *args, &block)
|
590
|
+
case method
|
591
|
+
when :comment
|
592
|
+
@attributes.fetch(method, "")
|
593
|
+
when :label
|
594
|
+
@attributes.fetch(method, to_s.split(/[\/\#]/).last)
|
595
|
+
when :type, :subClassOf, :subPropertyOf, :domain, :range
|
596
|
+
Array(@attributes[method]).map {|v| RDF::Vocabulary.expand_pname(v)}
|
597
|
+
else
|
598
|
+
super
|
599
|
+
end
|
314
600
|
end
|
315
601
|
end
|
602
|
+
end # Vocabulary
|
316
603
|
|
317
|
-
|
604
|
+
# Represents an RDF Vocabulary. The difference from {RDF::Vocabulary} is that
|
605
|
+
# that every concept in the vocabulary is required to be declared. To assist
|
606
|
+
# in this, an existing RDF representation of the vocabulary can be loaded as
|
607
|
+
# the basis for concepts being available
|
608
|
+
class StrictVocabulary < Vocabulary
|
609
|
+
class << self
|
610
|
+
# Redefines method_missing to the original definition
|
611
|
+
# By remaining a subclass of Vocabulary, we remain available to
|
612
|
+
# Vocabulary::each etc.
|
318
613
|
define_method(:method_missing, BasicObject.instance_method(:method_missing))
|
319
|
-
rescue NameError
|
320
|
-
define_method(:method_missing, Kernel.instance_method(:method_missing))
|
321
|
-
end
|
322
614
|
|
323
|
-
|
324
|
-
|
615
|
+
##
|
616
|
+
# Is this a strict vocabulary, or a liberal vocabulary allowing arbitrary properties?
|
617
|
+
def strict?; true; end
|
618
|
+
|
619
|
+
def [](name)
|
620
|
+
prop = super
|
621
|
+
props.fetch(prop) #raises KeyError on missing value
|
622
|
+
return prop
|
623
|
+
end
|
624
|
+
end
|
325
625
|
end # StrictVocabulary
|
326
626
|
end # RDF
|