rdf 3.1.15 → 3.2.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/README.md +40 -40
- data/VERSION +1 -1
- data/lib/rdf/mixin/countable.rb +5 -1
- data/lib/rdf/mixin/enumerable.rb +13 -1
- data/lib/rdf/mixin/queryable.rb +13 -1
- data/lib/rdf/model/list.rb +1 -1
- data/lib/rdf/model/literal/double.rb +1 -0
- data/lib/rdf/model/literal.rb +6 -12
- data/lib/rdf/model/statement.rb +3 -1
- data/lib/rdf/model/uri.rb +37 -8
- data/lib/rdf/nquads.rb +2 -2
- data/lib/rdf/ntriples/reader.rb +7 -7
- data/lib/rdf/ntriples/writer.rb +1 -1
- data/lib/rdf/reader.rb +1 -1
- data/lib/rdf/repository.rb +18 -94
- data/lib/rdf/transaction.rb +76 -2
- data/lib/rdf/util/file.rb +2 -2
- data/lib/rdf/util/logger.rb +8 -5
- data/lib/rdf/vocab/owl.rb +450 -445
- data/lib/rdf/vocab/rdfs.rb +89 -88
- data/lib/rdf/vocab/writer.rb +84 -51
- data/lib/rdf/vocab/xsd.rb +249 -249
- data/lib/rdf/vocabulary.rb +148 -137
- data/lib/rdf/writer.rb +2 -2
- data/lib/rdf.rb +0 -3
- metadata +22 -37
- data/lib/rdf/mixin/enumerator.rb +0 -40
data/lib/rdf/vocabulary.rb
CHANGED
@@ -5,7 +5,14 @@ module RDF
|
|
5
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_enum}).
|
6
6
|
#
|
7
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).
|
8
|
+
# Vocabularies can be defined based on {RDF::Vocabulary} or {RDF::StrictVocabulary} using a simple Domain Specific Language (DSL).
|
9
|
+
#
|
10
|
+
# * Ontology information for the vocabulary itself can be specified using the {ontology} method.
|
11
|
+
# * 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. Term attributes become properties of the associated {RDF::Vocabulary::Term} (see {RDF::Vocabulary::Term#attributes}).
|
12
|
+
#
|
13
|
+
# Note that, by default, the prefix associated with the vocabulary for forming and interpreting PNames is created from the class name of the vocabulary. See {\_\_prefix\_\_=} for overriding this at runtime.
|
14
|
+
#
|
15
|
+
# The simplest way to generate a DSL representation of a vocabulary is using {RDF::Vocabulary::Writer} given an {RDF::Graph} representation of the vocabulary.
|
9
16
|
#
|
10
17
|
# ### Vocabularies:
|
11
18
|
#
|
@@ -31,6 +38,31 @@ module RDF
|
|
31
38
|
# foaf.knows #=> RDF::URI("http://xmlns.com/foaf/0.1/knows")
|
32
39
|
# foaf[:name] #=> RDF::URI("http://xmlns.com/foaf/0.1/name")
|
33
40
|
# foaf['mbox'] #=> RDF::URI("http://xmlns.com/foaf/0.1/mbox")
|
41
|
+
#
|
42
|
+
# @example Defining a simple vocabulary
|
43
|
+
# EX = Class.new(RDF::StrictVocabulay("http://example/ns#")) do
|
44
|
+
# # Ontology definition
|
45
|
+
# ontology :"http://example/ns#",
|
46
|
+
# label: "The RDF Example Vocablary",
|
47
|
+
# type: "http://www.w3.org/2002/07/owl#Ontology"
|
48
|
+
#
|
49
|
+
# # Class definitions
|
50
|
+
# term :Class,
|
51
|
+
# label: "My Class",
|
52
|
+
# comment: "Good to use as an example",
|
53
|
+
# type: "rdfs:Class",
|
54
|
+
# subClassOf: "http://example/SuperClass",
|
55
|
+
# "ex:prop": "Some annotation property not having a shortcut"
|
56
|
+
#
|
57
|
+
# # Property definitions
|
58
|
+
# property :prop,
|
59
|
+
# comment: "A description of the property",
|
60
|
+
# label: "property",
|
61
|
+
# domain: "http://example/ns#Class",
|
62
|
+
# range: "rdfs:Literal",
|
63
|
+
# isDefinedBy: %(ex:),
|
64
|
+
# type: "rdf:Property"
|
65
|
+
# end
|
34
66
|
#
|
35
67
|
# @example Method calls are converted to the typical RDF camelcase convention
|
36
68
|
# foaf = RDF::Vocabulary.new("http://xmlns.com/foaf/0.1/")
|
@@ -44,17 +76,7 @@ module RDF
|
|
44
76
|
# graph = RDF::Graph.new << RDF::RDFS.to_enum
|
45
77
|
# graph.dump(:ntriples)
|
46
78
|
#
|
47
|
-
# @
|
48
|
-
# class EX < RDF::StrictVocabulay("http://example/ns#")
|
49
|
-
# term :Class,
|
50
|
-
# label: "My Class",
|
51
|
-
# comment: "Good to use as an example",
|
52
|
-
# "rdf:type" => "rdfs:Class",
|
53
|
-
# "rdfs:subClassOf" => "http://example/SuperClass"
|
54
|
-
# end
|
55
|
-
#
|
56
|
-
# @see http://www.w3.org/TR/curie/
|
57
|
-
# @see http://en.wikipedia.org/wiki/QName
|
79
|
+
# @see https://www.w3.org/TR/rdf-sparql-query/#prefNames
|
58
80
|
class Vocabulary
|
59
81
|
extend ::Enumerable
|
60
82
|
|
@@ -70,7 +92,7 @@ module RDF
|
|
70
92
|
# @return [Enumerator]
|
71
93
|
def each(&block)
|
72
94
|
if self.equal?(Vocabulary)
|
73
|
-
if @vocabs
|
95
|
+
if instance_variable_defined?(:@vocabs) && @vocabs
|
74
96
|
@vocabs.select(&:name).each(&block)
|
75
97
|
else
|
76
98
|
# This is needed since all vocabulary classes are defined using
|
@@ -177,16 +199,28 @@ module RDF
|
|
177
199
|
# @return [RDF::Vocabulary::Term]
|
178
200
|
#
|
179
201
|
# @overload property(name, options)
|
180
|
-
# Defines a new property or class in the vocabulary.
|
202
|
+
# Defines a new property or class in the vocabulary as a {RDF::Vocabulary::Term}.
|
181
203
|
#
|
182
204
|
# @example A simple term definition
|
183
205
|
# property :domain,
|
184
|
-
# comment: %(A domain of the subject property.)
|
185
|
-
# domain: "rdf:Property"
|
186
|
-
# label: "domain"
|
187
|
-
# range: "rdfs:Class"
|
188
|
-
# isDefinedBy: %(rdfs:)
|
189
|
-
# type: "rdf:Property"
|
206
|
+
# comment: %(A domain of the subject property.),
|
207
|
+
# domain: "rdf:Property",
|
208
|
+
# label: "domain",
|
209
|
+
# range: "rdfs:Class",
|
210
|
+
# isDefinedBy: %(rdfs:),
|
211
|
+
# type: "rdf:Property"
|
212
|
+
#
|
213
|
+
# @example A term definition with tagged values
|
214
|
+
# property :actor,
|
215
|
+
# comment: {en: "Subproperty of as:attributedTo that identifies the primary actor"},
|
216
|
+
# domain: "https://www.w3.org/ns/activitystreams#Activity",
|
217
|
+
# label: {en: "actor"},
|
218
|
+
# range: term(
|
219
|
+
# type: "http://www.w3.org/2002/07/owl#Class",
|
220
|
+
# unionOf: list("https://www.w3.org/ns/activitystreams#Object", "https://www.w3.org/ns/activitystreams#Link")
|
221
|
+
# ),
|
222
|
+
# subPropertyOf: "https://www.w3.org/ns/activitystreams#attributedTo",
|
223
|
+
# type: "http://www.w3.org/2002/07/owl#ObjectProperty"
|
190
224
|
#
|
191
225
|
# @example A SKOS term with anonymous values
|
192
226
|
# term: :af,
|
@@ -205,76 +239,8 @@ module RDF
|
|
205
239
|
# "foaf:name": "Aland Islands"
|
206
240
|
#
|
207
241
|
# @param [String, #to_s] name
|
208
|
-
# @param [Hash{Symbol=>String,Array<String
|
209
|
-
# Any other values are expected to expands to a {URI} using built-in vocabulary prefixes. The value is a `String`,
|
210
|
-
# @option options [String, Array<String,Term>] :type
|
211
|
-
# Shortcut for `rdf:type`, values are interpreted as a {Term}.
|
212
|
-
# @option options [String, Array<String>] :comment
|
213
|
-
# Shortcut for `rdfs:comment`, values are interpreted as a {Literal}.
|
214
|
-
# @option options [String, Array<String,Term>] :domain
|
215
|
-
# Shortcut for `rdfs:domain`, values are interpreted as a {Term}.
|
216
|
-
# @option options [String, Array<String,Term>] :isDefinedBy
|
217
|
-
# Shortcut for `rdfs:isDefinedBy`, values are interpreted as a {Term}.
|
218
|
-
# @option options [String, Array<String>] :label
|
219
|
-
# Shortcut for `rdfs:label`, values are interpreted as a {Literal}.
|
220
|
-
# @option options [String, Array<String,Term>] :range
|
221
|
-
# Shortcut for `rdfs:range`, values are interpreted as a {Term}.
|
222
|
-
# @option options [String, Array<String,Term>] :subClassOf
|
223
|
-
# Shortcut for `rdfs:subClassOf`, values are interpreted as a {Term}.
|
224
|
-
# @option options [String, Array<String,Term>] :subPropertyOf
|
225
|
-
# Shortcut for `rdfs:subPropertyOf`, values are interpreted as a {Term}.
|
226
|
-
# @option options [String, Array<String,Term>] :allValuesFrom
|
227
|
-
# Shortcut for `owl:allValuesFrom`, values are interpreted as a {Term}.
|
228
|
-
# @option options [String, Array<String,Term>] :cardinality
|
229
|
-
# Shortcut for `owl:cardinality`, values are interpreted as a {Literal}.
|
230
|
-
# @option options [String, Array<String,Term>] :equivalentClass
|
231
|
-
# Shortcut for `owl:equivalentClass`, values are interpreted as a {Term}.
|
232
|
-
# @option options [String, Array<String,Term>] :equivalentProperty
|
233
|
-
# Shortcut for `owl:equivalentProperty`, values are interpreted as a {Term}.
|
234
|
-
# @option options [String, Array<String,Term>] :intersectionOf
|
235
|
-
# Shortcut for `owl:intersectionOf`, values are interpreted as a {Term}.
|
236
|
-
# @option options [String, Array<String,Term>] :inverseOf
|
237
|
-
# Shortcut for `owl:inverseOf`, values are interpreted as a {Term}.
|
238
|
-
# @option options [String, Array<String,Term>] :maxCardinality
|
239
|
-
# Shortcut for `owl:maxCardinality`, values are interpreted as a {Literal}.
|
240
|
-
# @option options [String, Array<String,Term>] :minCardinality
|
241
|
-
# Shortcut for `owl:minCardinality`, values are interpreted as a {Literal}.
|
242
|
-
# @option options [String, Array<String,Term>] :onProperty
|
243
|
-
# Shortcut for `owl:onProperty`, values are interpreted as a {Term}.
|
244
|
-
# @option options [String, Array<String,Term>] :someValuesFrom
|
245
|
-
# Shortcut for `owl:someValuesFrom`, values are interpreted as a {Term}.
|
246
|
-
# @option options [String, Array<String,Term>] :unionOf
|
247
|
-
# Shortcut for `owl:unionOf`, values are interpreted as a {Term}.
|
248
|
-
# @option options [String, Array<String,Term>] :domainIncludes
|
249
|
-
# Shortcut for `schema:domainIncludes`, values are interpreted as a {Term}.
|
250
|
-
# @option options [String, Array<String,Term>] :rangeIncludes
|
251
|
-
# Shortcut for `schema:rangeIncludes`, values are interpreted as a {Term}.
|
252
|
-
# @option options [String, Array<String>] :altLabel
|
253
|
-
# Shortcut for `skos:altLabel`, values are interpreted as a {Literal}.
|
254
|
-
# @option options [String, Array<String,Term>] :broader
|
255
|
-
# Shortcut for `skos:broader`, values are interpreted as a {Term}.
|
256
|
-
# @option options [String, Array<String>] :definition
|
257
|
-
# Shortcut for `skos:definition`, values are interpreted as a {Literal}.
|
258
|
-
# @option options [String, Array<String>] :editorialNote
|
259
|
-
# Shortcut for `skos:editorialNote`, values are interpreted as a {Literal}.
|
260
|
-
# @option options [String, Array<String,Term>] :exactMatch
|
261
|
-
# Shortcut for `skos:exactMatch`, values are interpreted as a {Term}.
|
262
|
-
# @option options [String, Array<String,Term>] :hasTopConcept
|
263
|
-
# Shortcut for `skos:hasTopConcept`, values are interpreted as a {Term}.
|
264
|
-
# @option options [String, Array<String,Term>] :inScheme
|
265
|
-
# Shortcut for `skos:inScheme`, values are interpreted as a {Term}.
|
266
|
-
# @option options [String, Array<String,Term>] :member
|
267
|
-
# Shortcut for `skos:member`, values are interpreted as a {Term}.
|
268
|
-
# @option options [String, Array<String,Term>] :narrower
|
269
|
-
# Shortcut for `skos:narrower`, values are interpreted as a {Term}.
|
270
|
-
# @option options [String, Array<String>] :notation
|
271
|
-
# Shortcut for `skos:notation`, values are interpreted as a {Literal}.
|
272
|
-
# @option options [String, Array<String>] :note
|
273
|
-
# Shortcut for `skos:note`, values are interpreted as a {Literal}.
|
274
|
-
# @option options [String, Array<String>] :prefLabel
|
275
|
-
# Shortcut for `skos:prefLabel`, values are interpreted as a {Literal}.
|
276
|
-
# @option options [String, Array<String,Term>] :related
|
277
|
-
# Shortcut for `skos:related`, values are interpreted as a {Term}.
|
242
|
+
# @param [Hash{Symbol=>String,Array<String>}] options
|
243
|
+
# Any other values are expected to expands to a {URI} using built-in vocabulary prefixes. The value is a `String`, 'Hash{Symbol=>String,Array<String>}' or `Array<String,Hash{Symbol=>Array<String>}>` which is interpreted according to the `range` of the associated property and by heuristically determining the value datatype. See `attributes` argument to {Term#initialize}.
|
278
244
|
# @return [RDF::Vocabulary::Term]
|
279
245
|
def property(*args)
|
280
246
|
case args.length
|
@@ -287,15 +253,6 @@ module RDF
|
|
287
253
|
uri_str = [to_s, name.to_s].join('')
|
288
254
|
URI.cache.delete(uri_str.to_sym) # Clear any previous entry
|
289
255
|
|
290
|
-
# Transform attribute keys that are PNames with a warning
|
291
|
-
# FIXME: add back later
|
292
|
-
#if !@is_deprecated && options.is_a?(Hash) &&
|
293
|
-
# options.keys.map(&:to_s).any? {|k| k.include?(':') && !k.match?(/^https?:/)}
|
294
|
-
#
|
295
|
-
# @is_deprecated = true
|
296
|
-
# warn "[DEPRECATION] Vocabulary #{to_uri} includes pname attribute keys, regenerate"
|
297
|
-
#end
|
298
|
-
|
299
256
|
# Term attributes passed in a block for lazy evaluation. This helps to avoid load-time circular dependencies
|
300
257
|
prop = Term.intern(uri_str, vocab: self, attributes: options || {})
|
301
258
|
props[name.to_sym] = prop
|
@@ -356,7 +313,7 @@ module RDF
|
|
356
313
|
def ontology(*args)
|
357
314
|
case args.length
|
358
315
|
when 0
|
359
|
-
@ontology
|
316
|
+
@ontology if instance_variable_defined?(:@ontology)
|
360
317
|
else
|
361
318
|
uri, options = args
|
362
319
|
URI.cache.delete(uri.to_s.to_sym) # Clear any previous entry
|
@@ -379,15 +336,20 @@ module RDF
|
|
379
336
|
alias_method :__properties__, :properties
|
380
337
|
|
381
338
|
##
|
382
|
-
# Attempt to expand a Compact IRI/PName
|
339
|
+
# Attempt to expand a Compact IRI/PName using loaded vocabularies
|
383
340
|
#
|
384
341
|
# @param [String, #to_s] pname
|
342
|
+
# The local-part of the PName will will have [reserved character escapes](https://www.w3.org/TR/turtle/#reserved) unescaped.
|
385
343
|
# @return [Term]
|
386
|
-
# @raise [KeyError] if pname suffix not found in identified vocabulary
|
344
|
+
# @raise [KeyError] if pname suffix not found in identified vocabulary.
|
387
345
|
# @raise [ArgumentError] if resulting URI is not valid
|
388
346
|
def expand_pname(pname)
|
389
347
|
return pname unless pname.is_a?(String) || pname.is_a?(Symbol)
|
390
348
|
prefix, suffix = pname.to_s.split(":", 2)
|
349
|
+
# Unescape escaped PN_ESCAPE_CHARS
|
350
|
+
if suffix.match?(RDF::URI::PN_ESCAPES)
|
351
|
+
suffix = suffix.gsub(RDF::URI::PN_ESCAPES) {|matched| matched[1..-1]}
|
352
|
+
end
|
391
353
|
if prefix == "rdf"
|
392
354
|
RDF[suffix]
|
393
355
|
elsif vocab_detail = RDF::Vocabulary.vocab_map[prefix.to_sym]
|
@@ -417,9 +379,10 @@ module RDF
|
|
417
379
|
end
|
418
380
|
|
419
381
|
##
|
420
|
-
# Return the Vocabulary term associated with a
|
382
|
+
# Return the Vocabulary term associated with a URI
|
421
383
|
#
|
422
|
-
# @param [RDF::URI] uri
|
384
|
+
# @param [RDF::URI, String] uri
|
385
|
+
# If `uri` has is a pname in a locded vocabulary, the suffix portion of the PName will have escape characters unescaped before resolving against the vocabulary.
|
423
386
|
# @return [Vocabulary::Term]
|
424
387
|
def find_term(uri)
|
425
388
|
uri = RDF::URI(uri)
|
@@ -428,7 +391,8 @@ module RDF
|
|
428
391
|
if vocab.ontology == uri
|
429
392
|
vocab.ontology
|
430
393
|
else
|
431
|
-
|
394
|
+
suffix = uri.to_s[vocab.to_uri.to_s.length..-1].to_s
|
395
|
+
vocab[suffix]
|
432
396
|
end
|
433
397
|
end
|
434
398
|
end
|
@@ -507,7 +471,7 @@ module RDF
|
|
507
471
|
end
|
508
472
|
|
509
473
|
# Also include the ontology, if it's not also a property
|
510
|
-
@ontology.each_statement(&block) if
|
474
|
+
@ontology.each_statement(&block) if self.ontology && self.ontology != self
|
511
475
|
end
|
512
476
|
|
513
477
|
##
|
@@ -557,10 +521,6 @@ module RDF
|
|
557
521
|
statement.predicate.to_s.to_sym
|
558
522
|
end
|
559
523
|
|
560
|
-
# Skip literals other than plain or english
|
561
|
-
# This is because the ruby representation does not preserve language
|
562
|
-
next if statement.object.literal? && (statement.object.language || :en).to_s !~ /^en-?/
|
563
|
-
|
564
524
|
(term[key] ||= []) << statement.object
|
565
525
|
end
|
566
526
|
|
@@ -642,12 +602,31 @@ module RDF
|
|
642
602
|
alias_method :__name__, :name
|
643
603
|
|
644
604
|
##
|
645
|
-
# Returns a suggested
|
605
|
+
# Returns a suggested vocabulary prefix for this vocabulary class.
|
646
606
|
#
|
647
607
|
# @return [Symbol]
|
648
608
|
# @since 0.3.0
|
649
609
|
def __prefix__
|
650
|
-
|
610
|
+
instance_variable_defined?(:@__prefix__) ?
|
611
|
+
@__prefix__ :
|
612
|
+
__name__.split('::').last.downcase.to_sym
|
613
|
+
end
|
614
|
+
|
615
|
+
##
|
616
|
+
# Sets the vocabulary prefix to use for this vocabulary..
|
617
|
+
#
|
618
|
+
# @example Overriding a standard vocabulary prefix.
|
619
|
+
# RDF::Vocab::DC.__prefix__ = :dcterms
|
620
|
+
# RDF::Vocab::DC.title.pname #=> 'dcterms:title'
|
621
|
+
#
|
622
|
+
# @param [Symbol] prefix
|
623
|
+
# @return [Symbol]
|
624
|
+
# @since 3.2.3
|
625
|
+
def __prefix__=(prefix)
|
626
|
+
params = RDF::Vocabulary.vocab_map[__prefix__]
|
627
|
+
@__prefix__ = prefix.to_sym
|
628
|
+
RDF::Vocabulary.register(@__prefix__, self, **params)
|
629
|
+
@__prefix__
|
651
630
|
end
|
652
631
|
|
653
632
|
protected
|
@@ -937,6 +916,10 @@ module RDF
|
|
937
916
|
#
|
938
917
|
# Symbols which are accessors may also be looked up by their associated URI.
|
939
918
|
#
|
919
|
+
# Values may be Strings, Hash (Map), or Terms, or an Array including a combination of these. A Hash (Map) is used to create a datatype/language map to one or more string values which represent either datatyped literals, or language-tagged literals as interpreted by {#attribute_value}.
|
920
|
+
#
|
921
|
+
# In general, this accessor is used internally. The {#properties} method interprets these values as {RDF::Value}.
|
922
|
+
#
|
940
923
|
# @note lookup by PName is DEPRECATED and will be removed in a future version.
|
941
924
|
#
|
942
925
|
# @example looking up term label
|
@@ -945,23 +928,23 @@ module RDF
|
|
945
928
|
# RDF::RDFS.Literal.attributes[RDF::RDFS.label] #=> "Literal"
|
946
929
|
# RDF::RDFS.Literal.attributes["http://www.w3.org/2000/01/rdf-schema#label"] #=> "Literal"
|
947
930
|
# RDF::RDFS.Literal.attributes[:"http://www.w3.org/2000/01/rdf-schema#label"] #=> "Literal"
|
948
|
-
# @return [Hash{Symbol,
|
931
|
+
# @return [Hash{Symbol => String, Term, Hash{Symbol => String}, Array<String, Term, Hash{Symbol => String}>}]
|
932
|
+
# @see #properties
|
949
933
|
attr_reader :attributes
|
950
934
|
|
951
935
|
##
|
952
|
-
# @overload new(uri, attributes:, **options)
|
936
|
+
# @overload new(uri, attributes:, vocab:, **options)
|
953
937
|
# @param [URI, String, #to_s] uri
|
954
938
|
# @param [Vocabulary] vocab Vocabulary of this term.
|
955
|
-
# @param [Hash{Symbol => Symbol,Array<String,
|
939
|
+
# @param [Hash{Symbol => String,Term,Hash{Symbol=>String,Array<String>},Array<String>}] attributes ({})
|
956
940
|
# Attributes of this vocabulary term, used for finding `label` and `comment` and to serialize the term back to RDF. See {#attributes} and {#properties} for other ways to access.
|
957
941
|
# @param [Hash{Symbol => Object}] options
|
958
942
|
# Options from {URI#initialize}
|
959
943
|
#
|
960
|
-
# @overload new(attributes:, **options)
|
961
|
-
# @param [Hash{Symbol => Object}] options
|
944
|
+
# @overload new(attributes:, vocab:, **options)
|
962
945
|
# @param [Vocabulary] vocab Vocabulary of this term.
|
963
|
-
# @param [Hash{Symbol => Symbol,Array<String,
|
964
|
-
# Attributes of this vocabulary term, used for finding `label` and
|
946
|
+
# @param [Hash{Symbol => String,Term,Hash{Symbol=>String,Array<String>},Array<String>}] attributes ({})
|
947
|
+
# Attributes of this vocabulary term, used for finding `label`, `comment` and other term properties, and to serialize the term back to RDF. See {#attributes} and {#properties} for other ways to access.
|
965
948
|
# @param [Hash{Symbol => Object}] options
|
966
949
|
# Options from {URI#initialize}
|
967
950
|
def self.new(*args, vocab: nil, attributes: {}, **options)
|
@@ -1084,7 +1067,7 @@ module RDF
|
|
1084
1067
|
|
1085
1068
|
##
|
1086
1069
|
# Enumerate attributes with values transformed into {RDF::Value} instances
|
1087
|
-
# Uses an empty hash with a default_proc which looks up values in attributes.
|
1070
|
+
# Uses an empty hash with a default_proc which looks up values in attributes. The prevents specific attributes from being evaluated until acessed.
|
1088
1071
|
#
|
1089
1072
|
# Properties are indexed by symbol. Symbols directly interpreted by a term are the accessors defined for the {RDF::Vocabulary::Term} class, also in {Term::ATTR_URIs}. Other keys are interpreted as absolute URIs or PNames for properties defined on this term.
|
1090
1073
|
#
|
@@ -1101,12 +1084,27 @@ module RDF
|
|
1101
1084
|
# RDF::RDFS.Literal.properties[:"http://www.w3.org/2000/01/rdf-schema#label"] #=> RDF::Literal("Literal")
|
1102
1085
|
#
|
1103
1086
|
# @return [Hash{Symbol => Array<RDF::Value>}]
|
1087
|
+
# @see #attribute_value
|
1104
1088
|
def properties
|
1105
1089
|
Hash.new {|hash, key| attribute_value(key)}
|
1106
1090
|
end
|
1107
1091
|
|
1108
1092
|
##
|
1109
|
-
# Values of an attributes as {RDF::Value}
|
1093
|
+
# Values of an attributes as {RDF::Value}.
|
1094
|
+
#
|
1095
|
+
# Attribute values are returned as either an {RDF::Value} or {Array<RDf::Value} if there is more than one value.
|
1096
|
+
#
|
1097
|
+
# Attribute values which are not already a {RDF::Value} (including strings and symbols) are converted by a heuristic loookup as follows:
|
1098
|
+
#
|
1099
|
+
# * An {RDF::URI} if it can be turned into a valid IRI using {RDF::Vocabulary.expand_pname}. This includes IRIs already in non-relative form.
|
1100
|
+
# * A {Hash{Symbol=>String,Array<String>}} is interpreted as a datatype/language map. If the key contains a ':', it is treated as a PName or IRI datatype applied to the values. Otherwise, it is treated as a language-tag applied to the values.
|
1101
|
+
# * {RDF::Literal::Date} if valid,
|
1102
|
+
# * {RDF::Literal::DateTime} if valid,
|
1103
|
+
# * {RDF::Literal::Integer} if valid,
|
1104
|
+
# * {RDF::Literal::Decimal} if valid,
|
1105
|
+
# * {RDF::Literal::Double} if valid,
|
1106
|
+
# * {RDF::Literal::Boolean} if valid
|
1107
|
+
# * Otherwise, {RDF::Literal} where type may be inferred by the class of the value.
|
1110
1108
|
#
|
1111
1109
|
# @param [Symbol] prop
|
1112
1110
|
# @return [RDF::Value, Array<RDF::Value>]
|
@@ -1118,9 +1116,22 @@ module RDF
|
|
1118
1116
|
v = value.is_a?(Symbol) ? value.to_s : value
|
1119
1117
|
value = (RDF::Vocabulary.expand_pname(v) rescue nil) if v.is_a?(String) && v.include?(':')
|
1120
1118
|
value = value.to_uri if value.respond_to?(:to_uri)
|
1121
|
-
|
1119
|
+
value = if value.is_a?(RDF::Value) && value.valid?
|
1120
|
+
value
|
1121
|
+
elsif value.is_a?(Hash)
|
1122
|
+
# type/language map
|
1123
|
+
value.inject([]) do |memo, (k,v)|
|
1124
|
+
vv = [v] unless v.is_a?(Array)
|
1125
|
+
memo << if k.to_s.include?(':')
|
1126
|
+
dt = RDF::Vocabulary.expand_pname(v) rescue nil
|
1127
|
+
vv.map {|val| RDF::Literal(val, datatype: dt)}
|
1128
|
+
else
|
1129
|
+
vv.map {|val| RDF::Literal(val, language: k)}
|
1130
|
+
end
|
1131
|
+
end.flatten.compact.select(&:valid?)
|
1132
|
+
else
|
1122
1133
|
# Use as most appropriate literal
|
1123
|
-
|
1134
|
+
[
|
1124
1135
|
RDF::Literal::Date,
|
1125
1136
|
RDF::Literal::DateTime,
|
1126
1137
|
RDF::Literal::Integer,
|
@@ -1135,9 +1146,7 @@ module RDF
|
|
1135
1146
|
end
|
1136
1147
|
end
|
1137
1148
|
end
|
1138
|
-
|
1139
|
-
value
|
1140
|
-
end
|
1149
|
+
end.flatten
|
1141
1150
|
|
1142
1151
|
prop_values.length <= 1 ? prop_values.first : prop_values
|
1143
1152
|
end
|
@@ -1221,7 +1230,9 @@ module RDF
|
|
1221
1230
|
rangeIncludes
|
1222
1231
|
end
|
1223
1232
|
|
1224
|
-
|
1233
|
+
##
|
1234
|
+
# Serialize back to a Ruby source initializer. This is used primarily by {RDF::Vocabulary::Writer}.
|
1235
|
+
#
|
1225
1236
|
# @param [String] indent
|
1226
1237
|
# @return [String]
|
1227
1238
|
def to_ruby(indent: "")
|
@@ -1233,24 +1244,24 @@ module RDF
|
|
1233
1244
|
values = [values].compact unless values.is_a?(Array)
|
1234
1245
|
values = values.map do |value|
|
1235
1246
|
if value.is_a?(Literal) && %w(: comment definition notation note editorialNote).include?(k.to_s)
|
1236
|
-
"%(#{value.to_s.gsub('(', '\(').gsub(')', '\)')})
|
1237
|
-
|
1238
|
-
|
1247
|
+
"%(#{value.to_s.gsub('(', '\(').gsub(')', '\)')})"
|
1248
|
+
elsif value.node? && value.is_a?(RDF::Vocabulary::Term)
|
1249
|
+
"#{value.to_ruby(indent: indent + " ")}"
|
1239
1250
|
elsif value.is_a?(RDF::Term)
|
1240
|
-
"#{value.to_s.inspect}
|
1251
|
+
"#{value.to_s.inspect}"
|
1241
1252
|
elsif value.is_a?(RDF::List)
|
1242
1253
|
list_elements = value.map do |u|
|
1243
1254
|
if u.uri?
|
1244
|
-
"#{u.to_s.inspect}
|
1245
|
-
|
1246
|
-
|
1255
|
+
"#{u.to_s.inspect}"
|
1256
|
+
elsif u.node? && u.respond_to?(:to_ruby)
|
1257
|
+
u.to_ruby(indent: indent + " ")
|
1247
1258
|
else
|
1248
|
-
"#{u.to_s.inspect}
|
1259
|
+
"#{u.to_s.inspect}"
|
1249
1260
|
end
|
1250
1261
|
end
|
1251
1262
|
"list(#{list_elements.join(', ')})"
|
1252
1263
|
else
|
1253
|
-
"#{value.inspect}
|
1264
|
+
"#{value.inspect}"
|
1254
1265
|
end
|
1255
1266
|
end
|
1256
1267
|
"#{k.to_s.include?(':') ? k.to_s.inspect : k}: " +
|
@@ -1314,7 +1325,7 @@ module RDF
|
|
1314
1325
|
def [](name)
|
1315
1326
|
props.fetch(name.to_sym)
|
1316
1327
|
rescue KeyError
|
1317
|
-
raise KeyError, "#{name} not found in vocabulary #{self.__name__}"
|
1328
|
+
raise KeyError, "#{name.inspect} not found in vocabulary #{self.__name__}"
|
1318
1329
|
end
|
1319
1330
|
end
|
1320
1331
|
end # StrictVocabulary
|
data/lib/rdf/writer.rb
CHANGED
@@ -516,7 +516,7 @@ module RDF
|
|
516
516
|
when RDF::Literal then format_literal(term, **options)
|
517
517
|
when RDF::URI then format_uri(term, **options)
|
518
518
|
when RDF::Node then format_node(term, **options)
|
519
|
-
when RDF::Statement then
|
519
|
+
when RDF::Statement then format_quotedTriple(term, **options)
|
520
520
|
else nil
|
521
521
|
end
|
522
522
|
end
|
@@ -574,7 +574,7 @@ module RDF
|
|
574
574
|
# @return [String]
|
575
575
|
# @raise [NotImplementedError] unless implemented in subclass
|
576
576
|
# @abstract
|
577
|
-
def
|
577
|
+
def format_quotedTriple(value, **options)
|
578
578
|
raise NotImplementedError.new("#{self.class}#format_statement") # override in subclasses
|
579
579
|
end
|
580
580
|
|
data/lib/rdf.rb
CHANGED
@@ -7,9 +7,6 @@ require "ostruct"
|
|
7
7
|
require 'rdf/version'
|
8
8
|
require 'rdf/extensions'
|
9
9
|
|
10
|
-
# When loading, issue deprecation warning on forthcoming unsupported versions of Ruby
|
11
|
-
warn "[DEPRECATION] Ruby 2.4+ required in next version 3.1 of RDF.rb" if RUBY_VERSION < "2.4"
|
12
|
-
|
13
10
|
module RDF
|
14
11
|
# RDF mixins
|
15
12
|
autoload :Countable, 'rdf/mixin/countable'
|