rdf 3.2.2 → 3.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +37 -37
- 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/date.rb +27 -82
- data/lib/rdf/model/literal/datetime.rb +22 -122
- data/lib/rdf/model/literal/decimal.rb +12 -0
- data/lib/rdf/model/literal/double.rb +20 -0
- data/lib/rdf/model/literal/integer.rb +6 -0
- data/lib/rdf/model/literal/numeric.rb +154 -4
- data/lib/rdf/model/literal/temporal.rb +310 -0
- data/lib/rdf/model/literal/time.rb +26 -98
- data/lib/rdf/model/literal.rb +2 -1
- data/lib/rdf/model/statement.rb +3 -1
- data/lib/rdf/model/uri.rb +24 -3
- data/lib/rdf/ntriples/reader.rb +1 -1
- 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 +142 -132
- data/lib/rdf.rb +0 -3
- metadata +11 -5
- data/lib/rdf/mixin/enumerator.rb +0 -40
@@ -9,91 +9,41 @@ module RDF; class Literal
|
|
9
9
|
#
|
10
10
|
# @see http://www.w3.org/TR/xmlschema11-2/#time
|
11
11
|
# @since 0.2.1
|
12
|
-
class Time <
|
12
|
+
class Time < Temporal
|
13
13
|
DATATYPE = RDF::URI("http://www.w3.org/2001/XMLSchema#time")
|
14
14
|
GRAMMAR = %r(\A(\d{2}:\d{2}:\d{2}(?:\.\d+)?)((?:[\+\-]\d{2}:\d{2})|UTC|GMT|Z)?\Z).freeze
|
15
|
-
FORMAT = '%H:%M:%S.%L
|
15
|
+
FORMAT = '%H:%M:%S.%L'.freeze
|
16
16
|
|
17
17
|
##
|
18
|
+
# Internally, a `DateTime` is represented using a native `::DateTime`. If initialized from a `::DateTime`, the timezone is taken from that native object, otherwise, a timezone (or no timezone) is taken from the string representation having a matching `zzzzzz` component.
|
19
|
+
#
|
18
20
|
# @param [String, DateTime, #to_datetime] value
|
19
21
|
# @param (see Literal#initialize)
|
20
22
|
def initialize(value, datatype: nil, lexical: nil, **options)
|
21
23
|
@datatype = RDF::URI(datatype || self.class.const_get(:DATATYPE))
|
22
24
|
@string = lexical || (value if value.is_a?(String))
|
23
25
|
@object = case
|
24
|
-
when value.
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
##
|
31
|
-
# Converts this literal into its canonical lexical representation.
|
32
|
-
#
|
33
|
-
# §3.2.8.2 Canonical representation
|
34
|
-
#
|
35
|
-
# The canonical representation for time is defined by prohibiting
|
36
|
-
# certain options from the Lexical representation (§3.2.8.1).
|
37
|
-
# Specifically, either the time zone must be omitted or, if present, the
|
38
|
-
# time zone must be Coordinated Universal Time (UTC) indicated by a "Z".
|
39
|
-
# Additionally, the canonical representation for midnight is 00:00:00.
|
40
|
-
#
|
41
|
-
# @return [RDF::Literal] `self`
|
42
|
-
# @see http://www.w3.org/TR/xmlschema11-2/#time
|
43
|
-
def canonicalize!
|
44
|
-
if self.valid?
|
45
|
-
@string = if timezone?
|
46
|
-
@object.new_offset.new_offset.strftime(FORMAT[0..-4] + 'Z').sub('.000', '')
|
26
|
+
when value.respond_to?(:to_datetime)
|
27
|
+
dt = value.to_datetime
|
28
|
+
@zone = dt.zone
|
29
|
+
# Normalize to 1972-12-31 dateTime base
|
30
|
+
hms = dt.strftime(FORMAT)
|
31
|
+
::DateTime.parse("1972-12-31T#{hms}#{@zone}")
|
47
32
|
else
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
RDF::Literal(zone)
|
63
|
-
end
|
64
|
-
|
65
|
-
##
|
66
|
-
# Returns `true` if the value adheres to the defined grammar of the
|
67
|
-
# datatype.
|
68
|
-
#
|
69
|
-
# Special case for date and dateTime, for which '0000' is not a valid year
|
70
|
-
#
|
71
|
-
# @return [Boolean]
|
72
|
-
# @since 0.2.1
|
73
|
-
def valid?
|
74
|
-
super && !object.nil?
|
75
|
-
end
|
76
|
-
|
77
|
-
##
|
78
|
-
# Does the literal representation include a timezone? Note that this is only possible if initialized using a string, or `:lexical` option.
|
79
|
-
#
|
80
|
-
# @return [Boolean]
|
81
|
-
# @since 1.1.6
|
82
|
-
def timezone?
|
83
|
-
md = self.to_s.match(GRAMMAR)
|
84
|
-
md && !!md[2]
|
85
|
-
end
|
86
|
-
alias_method :tz?, :timezone?
|
87
|
-
alias_method :has_tz?, :timezone?
|
88
|
-
alias_method :has_timezone?, :timezone?
|
89
|
-
|
90
|
-
##
|
91
|
-
# Returns the value as a string.
|
92
|
-
# Does not normalize timezone
|
93
|
-
#
|
94
|
-
# @return [String]
|
95
|
-
def to_s
|
96
|
-
@string || @object.strftime(FORMAT).sub("+00:00", 'Z').sub('.000', '')
|
33
|
+
md = value.to_s.match(GRAMMAR)
|
34
|
+
_, tm, tz = Array(md)
|
35
|
+
if tz
|
36
|
+
@zone = tz == 'Z' ? '+00:00' : tz
|
37
|
+
else
|
38
|
+
@zone = nil # No timezone
|
39
|
+
end
|
40
|
+
# Normalize 24:00:00 to 00:00:00
|
41
|
+
hr, mi, se = tm.split(':')
|
42
|
+
hr = "%.2i" % (hr.to_i % 24) if hr.to_i > 23
|
43
|
+
value = "#{hr}:#{mi}:#{se}"
|
44
|
+
# Normalize to 1972-12-31 dateTime base
|
45
|
+
::DateTime.parse("1972-12-31T#{hr}:#{mi}:#{se}#{@zone}")
|
46
|
+
end rescue ::DateTime.new
|
97
47
|
end
|
98
48
|
|
99
49
|
##
|
@@ -104,32 +54,10 @@ module RDF; class Literal
|
|
104
54
|
def humanize(lang = :en)
|
105
55
|
t = object.strftime("%r")
|
106
56
|
if timezone?
|
107
|
-
|
108
|
-
|
109
|
-
else
|
110
|
-
" #{self.tz}"
|
111
|
-
end
|
57
|
+
z = @zone == '+00:00' ? "UTC" : @zone
|
58
|
+
t += " #{z}"
|
112
59
|
end
|
113
60
|
t
|
114
61
|
end
|
115
|
-
|
116
|
-
##
|
117
|
-
# Equal compares as Time objects
|
118
|
-
def ==(other)
|
119
|
-
# If lexically invalid, use regular literal testing
|
120
|
-
return super unless self.valid?
|
121
|
-
|
122
|
-
case other
|
123
|
-
when Literal::Time
|
124
|
-
return super unless other.valid?
|
125
|
-
# Compare as strings, as time includes a date portion, and adjusting for UTC
|
126
|
-
# can create a mismatch in the date portion.
|
127
|
-
self.object.new_offset.strftime('%H%M%S.%L') == other.object.new_offset.strftime('%H%M%S.%L')
|
128
|
-
when Literal::DateTime, Literal::Date
|
129
|
-
false
|
130
|
-
else
|
131
|
-
super
|
132
|
-
end
|
133
|
-
end
|
134
62
|
end # Time
|
135
63
|
end; end # RDF::Literal
|
data/lib/rdf/model/literal.rb
CHANGED
@@ -77,6 +77,7 @@ module RDF
|
|
77
77
|
require 'rdf/model/literal/decimal'
|
78
78
|
require 'rdf/model/literal/integer'
|
79
79
|
require 'rdf/model/literal/double'
|
80
|
+
require 'rdf/model/literal/temporal'
|
80
81
|
require 'rdf/model/literal/date'
|
81
82
|
require 'rdf/model/literal/datetime'
|
82
83
|
require 'rdf/model/literal/time'
|
@@ -295,7 +296,7 @@ module RDF
|
|
295
296
|
when self.simple? && other.simple?
|
296
297
|
self.value_hash == other.value_hash && self.value == other.value
|
297
298
|
when other.comperable_datatype?(self) || self.comperable_datatype?(other)
|
298
|
-
#
|
299
|
+
# Comparing plain with undefined datatypes does not generate an error, but returns false
|
299
300
|
# From data-r2/expr-equal/eq-2-2.
|
300
301
|
false
|
301
302
|
else
|
data/lib/rdf/model/statement.rb
CHANGED
@@ -71,6 +71,7 @@ module RDF
|
|
71
71
|
# @option options [RDF::Term] :graph_name (nil)
|
72
72
|
# Note, in RDF 1.1, a graph name MUST be an {Resource}.
|
73
73
|
# @option options [Boolean] :inferred used as a marker to record that this statement was inferred based on semantic relationships (T-Box).
|
74
|
+
# @option options [Boolean] :quoted used as a marker to record that this statement quoted and appears as the subject or object of another RDF::Statement.
|
74
75
|
# @return [RDF::Statement]
|
75
76
|
#
|
76
77
|
# @overload initialize(subject, predicate, object, **options)
|
@@ -83,6 +84,7 @@ module RDF
|
|
83
84
|
# @option options [RDF::Term] :graph_name (nil)
|
84
85
|
# Note, in RDF 1.1, a graph name MUST be an {Resource}.
|
85
86
|
# @option options [Boolean] :inferred used as a marker to record that this statement was inferred based on semantic relationships (T-Box).
|
87
|
+
# @option options [Boolean] :quoted used as a marker to record that this statement quoted and appears as the subject or object of another RDF::Statement.
|
86
88
|
# @return [RDF::Statement]
|
87
89
|
def initialize(subject = nil, predicate = nil, object = nil, options = {})
|
88
90
|
if subject.is_a?(Hash)
|
@@ -209,7 +211,7 @@ module RDF
|
|
209
211
|
##
|
210
212
|
# @return [Boolean]
|
211
213
|
def quoted?
|
212
|
-
|
214
|
+
!!@options[:quoted]
|
213
215
|
end
|
214
216
|
|
215
217
|
##
|
data/lib/rdf/model/uri.rb
CHANGED
@@ -111,6 +111,11 @@ module RDF
|
|
111
111
|
tag tel turn turns tv urn javascript
|
112
112
|
).freeze
|
113
113
|
|
114
|
+
# Characters in a PName which must be escaped
|
115
|
+
# Note: not all reserved characters need to be escaped in SPARQL/Turtle, but they must be unescaped when encountered
|
116
|
+
PN_ESCAPE_CHARS = /[~\.!\$&'\(\)\*\+,;=\/\?\#@%]/.freeze
|
117
|
+
PN_ESCAPES = /\\#{Regexp.union(PN_ESCAPE_CHARS, /[\-_]/)}/.freeze
|
118
|
+
|
114
119
|
##
|
115
120
|
# Cache size may be set through {RDF.config} using `uri_cache_size`.
|
116
121
|
#
|
@@ -627,10 +632,14 @@ module RDF
|
|
627
632
|
# RDF::URI('http://www.w3.org/2000/01/rdf-schema#').qname #=> [:rdfs, nil]
|
628
633
|
# RDF::URI('http://www.w3.org/2000/01/rdf-schema#label').qname #=> [:rdfs, :label]
|
629
634
|
# RDF::RDFS.label.qname #=> [:rdfs, :label]
|
635
|
+
# RDF::Vocab::DC.title.qname(
|
636
|
+
# prefixes: {dcterms: 'http://purl.org/dc/terms/'}) #=> [:dcterms, :title]
|
637
|
+
#
|
638
|
+
# @note within this software, the term QName is used to describe the tuple of prefix and suffix for a given IRI, where the prefix identifies some defined vocabulary. This somewhat contrasts with the notion of a [Qualified Name](https://www.w3.org/TR/2006/REC-xml-names11-20060816/#ns-qualnames) from XML, which are a subset of Prefixed Names.
|
630
639
|
#
|
631
640
|
# @param [Hash{Symbol => String}] prefixes
|
632
641
|
# Explicit set of prefixes to look for matches, defaults to loaded vocabularies.
|
633
|
-
# @return [Array(Symbol, Symbol)] or `nil` if no QName found
|
642
|
+
# @return [Array(Symbol, Symbol)] or `nil` if no QName found. The suffix component will not have [reserved characters](https://www.w3.org/TR/turtle/#reserved) escaped.
|
634
643
|
def qname(prefixes: nil)
|
635
644
|
if prefixes
|
636
645
|
prefixes.each do |prefix, uri|
|
@@ -659,13 +668,25 @@ module RDF
|
|
659
668
|
end
|
660
669
|
|
661
670
|
##
|
662
|
-
# Returns a
|
671
|
+
# Returns a Prefixed Name (PName) or the full IRI with any [reserved characters](https://www.w3.org/TR/turtle/#reserved) in the suffix escaped.
|
672
|
+
#
|
673
|
+
# @example Using a custom prefix for creating a PNname.
|
674
|
+
# RDF::URI('http://purl.org/dc/terms/creator').
|
675
|
+
# pname(prefixes: {dcterms: 'http://purl.org/dc/terms/'})
|
676
|
+
# #=> "dcterms:creator"
|
663
677
|
#
|
664
678
|
# @param [Hash{Symbol => String}] prefixes
|
665
679
|
# Explicit set of prefixes to look for matches, defaults to loaded vocabularies.
|
666
680
|
# @return [String] or `nil`
|
681
|
+
# @see #qname
|
682
|
+
# @see https://www.w3.org/TR/rdf-sparql-query/#prefNames
|
667
683
|
def pname(prefixes: nil)
|
668
|
-
|
684
|
+
q = self.qname(prefixes: prefixes)
|
685
|
+
return self.to_s unless q
|
686
|
+
prefix, suffix = q
|
687
|
+
suffix = suffix.to_s.gsub(PN_ESCAPE_CHARS) {|c| "\\#{c}"} if
|
688
|
+
suffix.to_s.match?(PN_ESCAPE_CHARS)
|
689
|
+
[prefix, suffix].join(":")
|
669
690
|
end
|
670
691
|
|
671
692
|
##
|
data/lib/rdf/ntriples/reader.rb
CHANGED
@@ -255,7 +255,7 @@ module RDF::NTriples
|
|
255
255
|
if !match(ST_END)
|
256
256
|
log_error("Expected end of statement (found: #{current_line.inspect})", lineno: lineno, exception: RDF::ReaderError)
|
257
257
|
end
|
258
|
-
RDF::Statement.new(subject, predicate, object)
|
258
|
+
RDF::Statement.new(subject, predicate, object, quoted: true)
|
259
259
|
end
|
260
260
|
end
|
261
261
|
|