rdf-edtf 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ce99d4757012d81466654f14a746edf6b1af5094
4
+ data.tar.gz: 631e8d3b07ee24555c790af3106464e983a0c623
5
+ SHA512:
6
+ metadata.gz: d9d9a547ae659cf53239a790e7cf7dbfacc457aa56e16dc0ad4a7cbe8ed82e6ace879946696f18d05768d45a32a35701b99a0baea11dd62eb70d829920566caa
7
+ data.tar.gz: 39f5ddb16660031cc928335b48c35e8642aab8d785ed7d95cc6cf219eb3ecaf5cdbc28e91f4e7f4a0a9f6bd91b1cf53ce145faf7b2c4ed45c7511565d6fde8a9
@@ -0,0 +1,3 @@
1
+ #*#
2
+ *~
3
+ Gemfile.lock
@@ -0,0 +1,10 @@
1
+ v0.1.0
2
+ ------
3
+
4
+ - Initial release
5
+ - Implements BNF grammar as a `Regexp` at `RDF::EDTF::Literal::GRAMMAR`
6
+ - Supports EDTF level 0-2, with minor caveats:
7
+ - Datetimes without a zone offset will be parsed and reserialized as UTC with
8
+ `+00:00`. See: https://github.com/inukshuk/edtf-ruby/issues/14
9
+ - Sets will be reserialized with spaces in their separators. See:
10
+ https://github.com/inukshuk/edtf-ruby/issues/15
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,45 @@
1
+ RDF::EDTF
2
+ =========
3
+
4
+ This is an `RDF::Literal` implementation around
5
+ [Extended Date Time Format](http://www.loc.gov/standards/datetime/pre-submission.html).
6
+
7
+ The underlying EDTF parser and implementation is provided by
8
+ [`edtf-ruby`](https://github.com/inukshuk/edtf-ruby/). The parser supports all
9
+ EDTF features, with caveats noted below.
10
+
11
+ Usage
12
+ -----
13
+
14
+ ```ruby
15
+ require 'rdf/edtf'
16
+
17
+ RDF::EDTF::Literal.new('1076?')
18
+ # or
19
+ RDF::Literal('1076?', datatype: RDF::EDTF::Literal::DATATYPE)
20
+ ```
21
+
22
+ Known Issues
23
+ ------------
24
+
25
+ - Datetimes without a zone offset will be parsed and reserialized as UTC with
26
+ `+00:00`. See: https://github.com/inukshuk/edtf-ruby/issues/14
27
+ - Sets will be reserialized with spaces in their separators. See:
28
+ https://github.com/inukshuk/edtf-ruby/issues/15
29
+
30
+ Contribution Guidelines
31
+ -----------------------
32
+
33
+ Please observe the following guidelines:
34
+
35
+ - Write tests for your contributions.
36
+ - Document methods you add using YARD annotations.
37
+ - Follow the included style guidelines (i.e. run `rubocop` before committing).
38
+ - Use well formed commit messages.
39
+
40
+ Do note that in order for us to merge any non-trivial changes (as a rule of thumb, additions larger than about 15 lines of code), we need an explicit public domain dedication on record from you.
41
+
42
+ License
43
+ -------
44
+
45
+ This is free and unencumbered public domain software. For more information, see http://unlicense.org/ or the accompanying {file:UNLICENSE} file.
@@ -0,0 +1,24 @@
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to <http://unlicense.org/>
File without changes
@@ -0,0 +1,21 @@
1
+ require 'rdf'
2
+
3
+ module RDF
4
+ ##
5
+ # A module implementing Extended Date Time Format (EDTF) handling for
6
+ # {RDF::Literal}.
7
+ #
8
+ # @example requiring RDF::EDTF
9
+ # require 'rdf/edtf'
10
+ #
11
+ # @example Initializing an EDTF literal with {RDF::Literal}
12
+ # RDF::Literal('107x', datatype: RDF::EDTF::Literal::DATATYPE)
13
+ #
14
+ # @see RDF::Literal
15
+ # @see http://www.loc.gov/standards/datetime/pre-submission.html the EDTF
16
+ # Specification
17
+ # @see http://id.loc.gov/datatypes/edtf.html
18
+ module EDTF
19
+ autoload :Literal, 'rdf/edtf/literal'
20
+ end
21
+ end
@@ -0,0 +1,159 @@
1
+ require 'edtf'
2
+
3
+ module RDF::EDTF
4
+ ##
5
+ # An EDTF Date literal
6
+ #
7
+ # @example Initializing an EDTF literal with {RDF::Literal}
8
+ # RDF::Literal('107x', datatype: RDF::EDTF::Literal::DATATYPE)
9
+ #
10
+ class Literal < RDF::Literal
11
+ DATATYPE = RDF::URI('http://id.loc.gov/datatypes/edtf/EDTF')
12
+
13
+ YEAR = %r(-*[0-9]{4}).freeze
14
+ ONETHRU12 = %r((01|02|03|04|05|06|07|08|09|10|11|12)).freeze
15
+ ONETHRU13 = Regexp.union(ONETHRU12, /13/).freeze
16
+ ONETHRU23 = Regexp.union(ONETHRU13, %r((14|15|16|17|18|19|20|21|22|23)))
17
+ .freeze
18
+ ZEROTHRU23 = Regexp.union(/00/, ONETHRU23).freeze
19
+ ONETHRU29 = Regexp.union(ONETHRU23, %r((24|25|26|27|28|29))).freeze
20
+ ONETHRU30 = Regexp.union(ONETHRU29, /30/).freeze
21
+ ONETHRU31 = Regexp.union(ONETHRU30, /31/).freeze
22
+
23
+ ONETHRU59 = Regexp.union(ONETHRU31,
24
+ %r((32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59)))
25
+ .freeze
26
+ ZEROTHRU59 = Regexp.union(/00/, ONETHRU59).freeze
27
+
28
+ POSITIVEDIGIT = %r((1|2|3|4|5|6|7|8|9)).freeze
29
+ DIGIT = Regexp.union(POSITIVEDIGIT, /0/).freeze
30
+
31
+ DAY = ONETHRU31
32
+ MONTH = ONETHRU12
33
+ MONTHDAY = %r(((01|03|05|07|08|10|12)-#{ONETHRU31})|((04|06|09|11)\-#{ONETHRU30})|(02\-#{ONETHRU29}))
34
+ .freeze
35
+ YEARMONTH = %r(#{YEAR}\-#{MONTH}).freeze
36
+ YEARMONTHDAY = %r(#{YEAR}\-#{MONTHDAY}).freeze
37
+ HOUR = ZEROTHRU23
38
+ MINUTE = ZEROTHRU59
39
+ SECOND = ZEROTHRU59
40
+
41
+ POSITIVEYEAR = %r((#{POSITIVEDIGIT}#{DIGIT}#{DIGIT}#{DIGIT})|(#{DIGIT}#{POSITIVEDIGIT}#{DIGIT}#{DIGIT})|(#{DIGIT}#{DIGIT}#{POSITIVEDIGIT}#{DIGIT})|(#{DIGIT}#{DIGIT}#{DIGIT}#{POSITIVEDIGIT})).freeze
42
+ NEGATIVEYEAR = %r(\-#{POSITIVEYEAR}).freeze
43
+ YYEAR = %r((#{POSITIVEYEAR}|#{NEGATIVEYEAR}|0000)).freeze
44
+ DATE = %r((#{YYEAR}|#{YEARMONTH}|#{YEARMONTHDAY})).freeze
45
+
46
+ BASETIME = %r((#{HOUR}\:#{MINUTE}\:#{SECOND}|(24\:00\:00))).freeze
47
+ # Zone offset is specified loosely, due to the issue documented here:
48
+ # https://github.com/inukshuk/edtf-ruby/issues/14
49
+ # The correct specification is:
50
+ # ZONEOFFSET = %r(Z|((\+|\-))(#{ONETHRU13}((\:#{MINUTE})|$)|14\:00|00\:#{ONETHRU59})).freeze
51
+ ZONEOFFSET = %r(Z|((\+|\-))(#{ONETHRU13}((\:#{MINUTE})|$)|14\:00|00\:#{MINUTE})).freeze
52
+ TIME = %r(#{BASETIME}(#{ZONEOFFSET}|$)).freeze
53
+ DATEANDTIME = %r(#{DATE}T#{TIME}).freeze
54
+
55
+ L0INTERVAL = %r(#{DATE}\/#{DATE}).freeze
56
+
57
+ LEVEL0EXPRESSION = Regexp.union(/^#{DATE}$/, /^#{DATEANDTIME}/, /^#{L0INTERVAL}$/).freeze
58
+
59
+ UASYMBOL = %r((\?|\~|\?\~)).freeze
60
+ SEASONNUMBER = %r((21|22|23|24)).freeze
61
+ SEASON = %r(#{YYEAR}\-#{SEASONNUMBER}).freeze
62
+ DATEORSEASON = %r((#{DATE}|#{SEASON})).freeze
63
+
64
+ UNCERTAINORAPPROXDATE = %r(#{DATE}#{UASYMBOL}).freeze
65
+ YEARWITHONEORTWOUNSPECIFEDDIGITS = %r(#{DIGIT}#{DIGIT}(#{DIGIT}|u)u).freeze
66
+ MONTHUNSPECIFIED = %r(#{YEAR}\-uu).freeze
67
+ DAYUNSPECIFIED = %r(#{YEARMONTH}\-uu).freeze
68
+ DAYANDMONTHUNSPECIFIED = %r(#{YEAR}\-uu\-uu).freeze
69
+ UNSPECIFIED = Regexp.union(YEARWITHONEORTWOUNSPECIFEDDIGITS,
70
+ MONTHUNSPECIFIED,
71
+ DAYUNSPECIFIED,
72
+ DAYANDMONTHUNSPECIFIED).freeze
73
+
74
+ L1START = %r((#{DATEORSEASON}(#{UASYMBOL})*)|unknown).freeze
75
+ L1END = %r((#{L1START}|open)).freeze
76
+
77
+ L1INTERVAL = %r(#{L1START}\/#{L1END}).freeze
78
+
79
+ LONGYEARSIMPLE = %r(y\-?#{POSITIVEDIGIT}#{DIGIT}#{DIGIT}#{DIGIT}#{DIGIT}+).freeze
80
+
81
+ LEVEL1EXPRESSION = %r(^(#{UNCERTAINORAPPROXDATE}|#{UNSPECIFIED}|#{L1INTERVAL}|#{LONGYEARSIMPLE}|#{SEASON})$).freeze
82
+
83
+ IUABASE = %r((#{YEAR}#{UASYMBOL}\-#{MONTH}(\-\(#{DAY}\)#{UASYMBOL})?|#{YEAR}#{UASYMBOL}\-#{MONTHDAY}#{UASYMBOL}?|#{YEAR}#{UASYMBOL}?\-\(#{MONTH}\)#{UASYMBOL}(\-\(#{DAY}\)#{UASYMBOL})?|#{YEAR}#{UASYMBOL}?\-\(#{MONTH}\)#{UASYMBOL}(\-#{DAY})?|#{YEARMONTH}#{UASYMBOL}\-\(#{DAY}\)#{UASYMBOL}|#{YEARMONTH}#{UASYMBOL}\-#{DAY}|#{YEARMONTH}\-\(#{DAY}\)#{UASYMBOL}|#{YEAR}\-\(#{MONTHDAY}\)#{UASYMBOL}|#{SEASON}#{UASYMBOL})).freeze
84
+
85
+ INTERNALUNCERTAINORAPPROXIMATE = %r(#{IUABASE}|\(#{IUABASE}\)#{UASYMBOL}).freeze
86
+
87
+ POSITIVEDIGITORU = %r(#{POSITIVEDIGIT}|u).freeze
88
+ DIGITORU = %r(#{POSITIVEDIGITORU}|0).freeze
89
+ ONETHRU3 = %r(1|2|3).freeze
90
+
91
+ YEARWITHU = %r(u#{DIGITORU}#{DIGITORU}#{DIGITORU}|#{DIGITORU}u#{DIGITORU}#{DIGITORU}|#{DIGITORU}#{DIGITORU}u#{DIGITORU}|#{DIGITORU}#{DIGITORU}#{DIGITORU}u)
92
+ DAYWITHU = %r(#{ONETHRU31}|u#{DIGITORU}|#{ONETHRU3}u)
93
+ MONTHWITHU = %r(#{ONETHRU12}|0u|1u|(u#{DIGITORU})).freeze
94
+
95
+ # these allow days out of range for the month given (e.g. 2013-02-31)
96
+ # is this a bug in the EDTF BNF?
97
+ YEARMONTHWITHU = %r((#{YEAR}|#{YEARWITHU})\-#{MONTHWITHU}|#{YEARWITHU}\-#{MONTH}).freeze
98
+ MONTHDAYWITHU = %r((#{MONTH}|#{MONTHWITHU})\-#{DAYWITHU}|#{MONTHWITHU}\-#{DAY}).freeze
99
+ YEARMONTHDAYWITHU = %r((#{YEARWITHU}|#{YEAR})\-#{MONTHDAYWITHU}|#{YEARWITHU}\-#{MONTHDAY}).freeze
100
+
101
+ INTERNALUNSPECIFIED = Regexp.union(YEARWITHU, YEARMONTHWITHU, YEARMONTHDAYWITHU).freeze
102
+
103
+ DATEWITHINTERNALUNCERTAINTY = Regexp.union(INTERNALUNCERTAINORAPPROXIMATE, INTERNALUNSPECIFIED).freeze
104
+
105
+ EARLIER = %r(\.\.#{DATE}).freeze
106
+ LATER = %r(#{DATE}\.\.).freeze
107
+ CONSECUTIVES = %r(#{YEARMONTHDAY}\.\.#{YEARMONTHDAY}|#{YEARMONTH}\.\.#{YEARMONTH}|#{YEAR}\.\.#{YEAR}).freeze
108
+
109
+ LISTELEMENT = %r(#{DATE}|#{DATEWITHINTERNALUNCERTAINTY}|#{UNCERTAINORAPPROXDATE}|#{UNSPECIFIED}|#{CONSECUTIVES}).freeze
110
+ # list contents are specified here to allow spaces:
111
+ # e.g. [1995, 1996, 1997]
112
+ # this is not allowed in the specification's grammar
113
+ # see: https://github.com/inukshuk/edtf-ruby/issues/15
114
+ LISTCONTENT = %r((#{EARLIER}(\,\s?#{LISTELEMENT})*|(#{EARLIER}\,\s?)?(#{LISTELEMENT}\,\s?)*#{LATER}|#{LISTELEMENT}(\,\s?#{LISTELEMENT})+|#{CONSECUTIVES})).freeze
115
+
116
+ CHOICELIST = %r(\[#{LISTCONTENT}\]).freeze
117
+ INCLUSIVELIST = %r(\{#{LISTCONTENT}\}).freeze
118
+
119
+ MASKEDPRECISION = %r(#{DIGIT}#{DIGIT}((#{DIGIT}x)|xx)).freeze
120
+
121
+ L2INTERVAL = %r((#{DATEORSEASON}\/#{DATEWITHINTERNALUNCERTAINTY})|(#{DATEWITHINTERNALUNCERTAINTY}\/#{DATEORSEASON})|(#{DATEWITHINTERNALUNCERTAINTY}\/#{DATEWITHINTERNALUNCERTAINTY})).freeze
122
+
123
+ POSITIVEINTEGER = %r(#{POSITIVEDIGIT}#{DIGIT}*).freeze
124
+ LONGYEARSCIENTIFIC = %r(y\-?#{POSITIVEINTEGER}e#{POSITIVEINTEGER}(p#{POSITIVEINTEGER})?).freeze
125
+
126
+ QUALIFYINGSTRING = %r(\S+).freeze
127
+ SEASONQUALIFIED = %r(#{SEASON}\^#{QUALIFYINGSTRING}).freeze
128
+
129
+ LEVEL2EXPRESSION = %r(^(#{INTERNALUNCERTAINORAPPROXIMATE}|#{INTERNALUNSPECIFIED}|#{CHOICELIST}|#{INCLUSIVELIST}|#{MASKEDPRECISION}|#{L2INTERVAL}|#{LONGYEARSCIENTIFIC}|#{SEASONQUALIFIED})$).freeze
130
+
131
+ ##
132
+ # Grammar is articulated according to the BNF in the EDTF 1.0 pre-submission
133
+ # specification, except where noted above.
134
+ #
135
+ # @todo investigate the allowance for out-of-range days (e.g. 2013-02-31) in
136
+ # `INTERNALUNSPECIFIED`
137
+ # @todo follow up on zone offset `00:00`; disallow, if appropriate, once
138
+ # {https://github.com/inukshuk/edtf-ruby/issues/14} is closed
139
+ # @todo disallow spaces in LISTCONTENT when
140
+ # {https://github.com/inukshuk/edtf-ruby/issues/15} is closed
141
+ #
142
+ # @see http://www.loc.gov/standards/datetime/pre-submission.html#bnf
143
+ GRAMMAR = Regexp.union(LEVEL0EXPRESSION, LEVEL1EXPRESSION, LEVEL2EXPRESSION).freeze
144
+
145
+ ##
146
+ # Initializes an RDF::Literal with EDTF datatype.
147
+ #
148
+ # Casts lexical values with the correct datatype to EDTF, if they are
149
+ # parsable. Otherwise retains their original value as an `#invalid?`
150
+ # literal.
151
+ #
152
+ # @see RDF::Literal
153
+ def initialize(value, options = {})
154
+ value = EDTF.parse(value) || value
155
+ @string = value.edtf if value.respond_to? :edtf
156
+ super
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,5 @@
1
+ module RDF
2
+ module EDTF
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'rdf/edtf/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rdf-edtf"
7
+ s.version = RDF::EDTF::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ['Tom Johnson']
10
+ s.homepage = 'https://github.com/dpla/rdf-edtf'
11
+ s.email = 'tom@dp.la'
12
+ s.summary = %q{An `RDF::Literal` implementation around Extended Date Time Format.}
13
+ s.description = %q{Supports serializing and parsing EDTF (all levels) as typed literals in RDF.}
14
+ s.license = 'UNLICENSE'
15
+ s.required_ruby_version = '>= 2.0.0'
16
+
17
+ s.add_dependency('rdf', '~> 1.1')
18
+ s.add_dependency('edtf', '~>2.1.0')
19
+
20
+ s.add_development_dependency('pry')
21
+ s.add_development_dependency('rspec')
22
+ s.add_development_dependency('rdf-spec')
23
+
24
+ s.files = `git ls-files`.split("\n")
25
+ s.test_files = `git ls-files -- {spec}/*`.split("\n")
26
+
27
+ s.extra_rdoc_files = ['UNLICENSE',
28
+ 'README.md']
29
+ end
@@ -0,0 +1,174 @@
1
+ require 'spec_helper'
2
+
3
+ describe RDF::EDTF::Literal do
4
+ it_behaves_like 'RDF::Literal with datatype',
5
+ EDTF.parse!('1076'),
6
+ 'http://id.loc.gov/datatypes/edtf/EDTF'
7
+
8
+ let(:date) { EDTF.parse('1076') }
9
+ subject { described_class.new(EDTF.parse!('1076')) }
10
+
11
+ describe '#initialize' do
12
+ context 'with string' do
13
+ let(:date) { '199u' }
14
+
15
+ it 'casts object value to EDTF' do
16
+ expect(described_class.new(date).object).to eq EDTF.parse(date)
17
+ end
18
+
19
+ it 'sets lexical value' do
20
+ expect(described_class.new(date).value).to eq date
21
+ end
22
+
23
+ context 'as invalid edtf' do
24
+ let(:date) { 'not a valid edtf date' }
25
+
26
+ it 'retains original value as object' do
27
+ expect(described_class.new(date).object).to eq date
28
+ end
29
+
30
+ it 'gives #to_s as lexical value' do
31
+ expect(described_class.new(date).value).to eq date.to_s
32
+ end
33
+ end
34
+ end
35
+
36
+ it 'gives value if invalid edtf' do
37
+ date = '19!!'
38
+ expect(described_class.new(date).object).to eq date
39
+ end
40
+ end
41
+
42
+ describe '#<=>' do
43
+ it 'is less than succeding date' do
44
+ expect(subject).to be < described_class.new(date.succ)
45
+ end
46
+
47
+ it 'is greater than than previous date' do
48
+ expect(subject).to be > described_class.new(date.prev)
49
+ end
50
+
51
+ it 'is not equal to date of different precision' do
52
+ day_date = date.clone
53
+ day_date.precision = :day
54
+ expect(subject).not_to eq described_class.new(day_date)
55
+ end
56
+
57
+ it 'is not equal to date of different approximation' do
58
+ approx_date = date.clone
59
+ approx_date.approximate!
60
+ expect(subject).not_to eq described_class.new(approx_date)
61
+ end
62
+ end
63
+
64
+ describe '#value' do
65
+ it 'gives an edtf string representation' do
66
+ expect(subject.value).to eq date.edtf
67
+ end
68
+ end
69
+ end
70
+
71
+ describe RDF::Literal do
72
+ include_examples 'RDF::Literal lookup',
73
+ { RDF::EDTF::Literal::DATATYPE => RDF::EDTF::Literal }
74
+
75
+ include_examples 'RDF::Literal canonicalization',
76
+ RDF::EDTF::Literal::DATATYPE,
77
+ {}
78
+
79
+ include_examples 'RDF::Literal validation',
80
+ RDF::EDTF::Literal::DATATYPE,
81
+ # valid value examples taken from:
82
+ # http://www.loc.gov/standards/datetime/pre-submission.html
83
+ ['2001-02-03',
84
+ '2008-12',
85
+ '2008',
86
+ '-2008',
87
+ '0000',
88
+ '2001-02-03T09:30:01',
89
+ '2004-01-01T10:10:10Z',
90
+ '2004-01-01T10:10:10+05:00',
91
+ '1964/2008',
92
+ '2004-06/2006-08',
93
+ '2004-02-01/2005-02-08',
94
+ '2004-02-01/2005-02',
95
+ '2004-02-01/2005',
96
+ '2005/2006-02',
97
+ '1984?',
98
+ '2004-06?',
99
+ '2004-06-11?',
100
+ '1984~',
101
+ '1984?~',
102
+ '199u',
103
+ '19uu',
104
+ '1999-uu',
105
+ '1999-01-uu',
106
+ '1999-uu-uu',
107
+ '2004-06-01/unknown',
108
+ '2004-01-01/open',
109
+ '1984~/2004-06',
110
+ '1984/2004-06~',
111
+ '1984?/2004?~',
112
+ 'y170000002',
113
+ 'y-170000002',
114
+ '2001-21',
115
+ '2001-22',
116
+ '2001-23',
117
+ '2001-24',
118
+ '2004?-06-11',
119
+ '2004-06~-11',
120
+ '2004-(06)?-11',
121
+ '2004-06-(11)~',
122
+ '2004-(06)?~',
123
+ '2004-(06-11)?',
124
+ '2004?-06-(11)~',
125
+ '(2004-(06)~)?',
126
+ '2004?-(06)?~',
127
+ # in addition to being unsupproed by EDTF.parse, these
128
+ # appear to be disallowed by EDTF's BNF:
129
+ # '(2004)?-06-04~', # unsupported; EDTF.parse returns nil
130
+ # '(2011)-06-04~', # unsupported; EDTF.parse returns nil,
131
+ '2011-(06-04)~',
132
+ '2011-23~',
133
+ '156u-12-25',
134
+ '15uu-12-25',
135
+ '15uu-12-uu',
136
+ '1560-uu-25',
137
+ '[1667,1668,1670..1672]',
138
+ '[..1760-12-03]',
139
+ '[1760-12..]',
140
+ '[1760-01,1760-02,1760-12..]',
141
+ '[1667,1760-12]',
142
+ '{1667,1668,1670..1672}',
143
+ '{1960,1961-12}',
144
+ '196x',
145
+ '19xx',
146
+ '2004-06-(01)~/2004-06-(20)~',
147
+ '2004-06-uu/2004-07-03',
148
+ 'y17e7',
149
+ 'y-17e7',
150
+ 'y17101e4p3', # unsupported; EDTF.parse returns nil
151
+ '2001-21^southernHemisphere'],
152
+ ['abc', '123', '1921-1', '100000', '1923-13', '192?',
153
+ '1924a', '1234-22abc', '1xxx']
154
+
155
+ describe 'initializing with datatype' do
156
+ subject { RDF::Literal(date, datatype: RDF::EDTF::Literal::DATATYPE) }
157
+
158
+ context 'with edtf value' do
159
+ let(:date) { EDTF.parse!('1076') }
160
+
161
+ it 'sets date to object' do
162
+ expect(subject.object).to eql date
163
+ end
164
+ end
165
+
166
+ context 'with edtf value' do
167
+ let(:date) { '1076' }
168
+
169
+ it 'parses date to edtf' do
170
+ expect(subject.object).to eq EDTF.parse(date)
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,18 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup
3
+
4
+ require 'rdf/edtf'
5
+
6
+ # Load support files
7
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
8
+
9
+ RSpec.configure do |config|
10
+ config.color = true
11
+ config.tty = true
12
+
13
+ # Uncomment the following line to get errors and backtrace for deprecation warnings
14
+ # config.raise_errors_for_deprecations!
15
+
16
+ # Use the specified formatter
17
+ config.formatter = :progress
18
+ end
@@ -0,0 +1,123 @@
1
+
2
+ shared_examples 'RDF::Literal with datatype' do |value, datatype_uri|
3
+ subject { described_class.new(value) }
4
+
5
+ it 'has a DATATYPE' do
6
+ expect(described_class::DATATYPE).to be_a RDF::URI
7
+ end
8
+
9
+ it 'has a GRAMMAR' do
10
+ expect(described_class::GRAMMAR).to respond_to :=~
11
+ end
12
+
13
+ it { is_expected.to be_literal }
14
+ it { is_expected.to be_typed }
15
+ it { is_expected.not_to be_plain }
16
+ it { is_expected.not_to be_anonymous }
17
+
18
+ it 'has correct datatype' do
19
+ expect(subject.datatype).to eq datatype_uri
20
+ end
21
+
22
+ describe '#==' do
23
+ it { is_expected.to eq subject }
24
+ it { expect(subject.object).to eq value }
25
+ it { is_expected.not_to eq described_class.new('OTHER') }
26
+ it { is_expected.not_to eq nil }
27
+ end
28
+
29
+ describe '#humanize' do
30
+ it 'gives a string representation' do
31
+ expect(subject.humanize).to be_a String
32
+ end
33
+ end
34
+
35
+ describe '#to_s' do
36
+ it 'gives a string representation' do
37
+ expect(subject.to_s).to be_a String
38
+ end
39
+ end
40
+
41
+ describe '#object' do
42
+ it 'is the given value' do
43
+ expect(subject.humanize).to be_a String
44
+ end
45
+ end
46
+ end
47
+
48
+ shared_examples 'RDF::Literal lookup' do |uri_hash|
49
+ uri_hash.each do |uri, klass|
50
+ it "finds #{klass} for #{uri}" do
51
+ expect(RDF::Literal("0", :datatype => uri).class).to eq klass
52
+ end
53
+ end
54
+ end
55
+
56
+ shared_examples 'RDF::Literal canonicalization' do |datatype, pairs|
57
+ pairs.each do |value, str|
58
+
59
+ klass = RDF::Literal.datatyped_class(datatype.to_s)
60
+
61
+ it "does not normalize '#{value}' by default" do
62
+ expect(RDF::Literal.new(value,
63
+ datatype: datatype ,
64
+ canonicalize: false).to_s)
65
+ .to eq value
66
+ end
67
+
68
+ it "normalizes double '#{value}' to '#{str}'" do
69
+ expect(RDF::Literal.new(value,
70
+ datatype: datatype,
71
+ canonicalize: true).to_s)
72
+ .to eq str
73
+ end
74
+
75
+ it "humanizes double '#{value}' to '#{str}'" do
76
+ expect(RDF::Literal.new(value,
77
+ datatype: datatype,
78
+ canonicalize: false).humanize)
79
+ .to eq value
80
+ end
81
+
82
+ it "instantiates '#{value}' as #{klass}" do
83
+ expect(RDF::Literal.new(value,
84
+ datatype: datatype,
85
+ canonicalize: true))
86
+ .to be_a(klass)
87
+ end
88
+
89
+ it "causes normalized '#{value}' to be == '#{str}'" do
90
+ expect(RDF::Literal.new(value,
91
+ datatype: datatype,
92
+ canonicalize: true))
93
+ .to eq RDF::Literal.new(str, datatype: datatype, canonicalize: false)
94
+ end
95
+ end
96
+ end
97
+
98
+ shared_examples 'RDF::Literal validation' do |datatype,
99
+ valid_values,
100
+ invalid_values|
101
+
102
+ klass = RDF::Literal.datatyped_class(datatype.to_s)
103
+
104
+ valid_values.each do |value|
105
+ it "validates #{klass} '#{value}'" do
106
+ expect(RDF::Literal.new(value, datatype: datatype)).to be_valid
107
+ end
108
+
109
+ it "does not invalidate #{klass} '#{value}'" do
110
+ expect(RDF::Literal.new(value, datatype: datatype)).not_to be_invalid
111
+ end
112
+ end
113
+
114
+ invalid_values.each do |value|
115
+ it "invalidates #{klass} '#{value}'" do
116
+ expect(RDF::Literal.new(value, datatype: datatype)).to be_invalid
117
+ end
118
+
119
+ it "does not validate #{klass} '#{value}'" do
120
+ expect(RDF::Literal.new(value, datatype: datatype)).not_to be_valid
121
+ end
122
+ end
123
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rdf-edtf
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tom Johnson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rdf
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: edtf
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.1.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.1.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rdf-spec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Supports serializing and parsing EDTF (all levels) as typed literals
84
+ in RDF.
85
+ email: tom@dp.la
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files:
89
+ - UNLICENSE
90
+ - README.md
91
+ files:
92
+ - ".gitignore"
93
+ - CHANGELOG.md
94
+ - Gemfile
95
+ - README.md
96
+ - UNLICENSE
97
+ - lib/rdf.rb
98
+ - lib/rdf/edtf.rb
99
+ - lib/rdf/edtf/literal.rb
100
+ - lib/rdf/edtf/version.rb
101
+ - rdf-edtf.gemspec
102
+ - spec/edtf_spec.rb
103
+ - spec/spec_helper.rb
104
+ - spec/support/shared_examples/literal.rb
105
+ homepage: https://github.com/dpla/rdf-edtf
106
+ licenses:
107
+ - UNLICENSE
108
+ metadata: {}
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: 2.0.0
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 2.2.1
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: An `RDF::Literal` implementation around Extended Date Time Format.
129
+ test_files: []
130
+ has_rdoc: