wikidatum 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_value_type/base'
4
+
5
+ # The Globe Coordinate type datavalue JSON looks like this:
6
+ #
7
+ # ```json
8
+ # {
9
+ # "datavalue": {
10
+ # "value": {
11
+ # "latitude": 52.516666666667,
12
+ # "longitude": 13.383333333333,
13
+ # "precision": 0.016666666666667,
14
+ # "globe": "http://www.wikidata.org/entity/Q2"
15
+ # },
16
+ # "type": "globecoordinate"
17
+ # }
18
+ # }
19
+ # ```
20
+ class Wikidatum::DataValueType::GlobeCoordinate
21
+ # @return [Float]
22
+ attr_reader :latitude
23
+
24
+ # @return [Float]
25
+ attr_reader :longitude
26
+
27
+ # @return [Float]
28
+ attr_reader :precision
29
+
30
+ # @return [String] A URL (usually in the same Wikibase instance) representing the given globe model (e.g. Earth).
31
+ attr_reader :globe
32
+
33
+ # @param latitude [Float]
34
+ # @param longitude [Float]
35
+ # @param precision [Float]
36
+ # @param globe [String]
37
+ # @return [void]
38
+ def initialize(latitude:, longitude:, precision:, globe:)
39
+ @latitude = latitude
40
+ @longitude = longitude
41
+ @precision = precision
42
+ @globe = globe
43
+ end
44
+
45
+ # @return [Hash]
46
+ def to_h
47
+ {
48
+ latitude: @latitude,
49
+ longitude: @longitude,
50
+ precision: @precision,
51
+ globe: @globe
52
+ }
53
+ end
54
+
55
+ # The "type" value used by Wikibase, for use when creating/updating statements.
56
+ #
57
+ # @return [String]
58
+ def wikibase_type
59
+ 'globecoordinate'
60
+ end
61
+
62
+ # The "datatype" value used by Wikibase, usually identical to wikibase_type
63
+ # but not always.
64
+ #
65
+ # @return [String]
66
+ def wikibase_datatype
67
+ 'globe-coordinate' # yes, really
68
+ end
69
+
70
+ # @!visibility private
71
+ def self.marshal_load(data_value_json)
72
+ Wikidatum::DataValueType::Base.new(
73
+ type: :globe_coordinate,
74
+ value: new(
75
+ latitude: data_value_json['latitude'],
76
+ longitude: data_value_json['longitude'],
77
+ precision: data_value_json['precision'],
78
+ globe: data_value_json['globe']
79
+ )
80
+ )
81
+ end
82
+
83
+ # @!visibility private
84
+ def marshal_dump
85
+ {
86
+ latitude: @latitude,
87
+ longitude: @longitude,
88
+ precision: @precision,
89
+ globe: @globe
90
+ }
91
+ end
92
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_value_type/base'
4
+
5
+ # The Monolingual Text type datavalue JSON looks like this:
6
+ #
7
+ # ```json
8
+ # {
9
+ # "datavalue": {
10
+ # "value": {
11
+ # "text": "South Pole Telescope eyes birth of first massive galaxies",
12
+ # "language": "en"
13
+ # },
14
+ # "type": "monolingualtext"
15
+ # }
16
+ # }
17
+ # ```
18
+ class Wikidatum::DataValueType::MonolingualText
19
+ # @return [String] the language code, e.g. 'en'
20
+ attr_reader :language
21
+
22
+ # @return [String]
23
+ attr_reader :text
24
+
25
+ # @param language [String]
26
+ # @param text [String]
27
+ # @return [void]
28
+ def initialize(language:, text:)
29
+ @language = language
30
+ @text = text
31
+ end
32
+
33
+ # @return [Hash]
34
+ def to_h
35
+ {
36
+ language: @language,
37
+ text: @text
38
+ }
39
+ end
40
+
41
+ # The "type" value used by Wikibase, for use when creating/updating statements.
42
+ #
43
+ # @return [String]
44
+ def wikibase_type
45
+ 'monolingualtext'
46
+ end
47
+
48
+ # The "datatype" value used by Wikibase, usually identical to wikibase_type
49
+ # but not always.
50
+ #
51
+ # @return [String]
52
+ def wikibase_datatype
53
+ wikibase_type
54
+ end
55
+
56
+ # @!visibility private
57
+ def self.marshal_load(data_value_json)
58
+ Wikidatum::DataValueType::Base.new(
59
+ type: :monolingual_text,
60
+ value: new(
61
+ language: data_value_json['language'],
62
+ text: data_value_json['text']
63
+ )
64
+ )
65
+ end
66
+
67
+ # @!visibility private
68
+ def marshal_dump
69
+ {
70
+ language: @language,
71
+ text: @text
72
+ }
73
+ end
74
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_value_type/base'
4
+
5
+ # The NoValue type actually has no datavalue key in the blob at all. We work
6
+ # around this by just passing nil to the serializer.
7
+
8
+ # Represents "no value".
9
+ class Wikidatum::DataValueType::NoValue < Wikidatum::DataValueType::Base
10
+ # The "type" value used by Wikibase, for use when creating/updating statements.
11
+ #
12
+ # @return [String]
13
+ def wikibase_type
14
+ 'string'
15
+ end
16
+
17
+ # The "datatype" value used by Wikibase, usually identical to wikibase_type
18
+ # but not always.
19
+ #
20
+ # @return [String]
21
+ def wikibase_datatype
22
+ wikibase_type
23
+ end
24
+
25
+ # @!visibility private
26
+ def self.marshal_load(_data_value_json)
27
+ new(type: :no_value, value: nil)
28
+ end
29
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_value_type/base'
4
+
5
+ # The Quantity type datavalue JSON looks like this:
6
+ #
7
+ # ```json
8
+ # {
9
+ # "datavalue": {
10
+ # "value": {
11
+ # "amount": "+10.38",
12
+ # "upperBound": "+10.375",
13
+ # "lowerBound": "+10.385",
14
+ # "unit": "http://www.wikidata.org/entity/Q712226"
15
+ # },
16
+ # "type": "quantity"
17
+ # }
18
+ # }
19
+ # ```
20
+ class Wikidatum::DataValueType::Quantity
21
+ # @return [String] A string value like "+2", usually an integer but not always.
22
+ attr_reader :amount
23
+
24
+ # @return [String, nil] upper bound, if one is defined.
25
+ attr_reader :upper_bound
26
+
27
+ # @return [String, nil] lower bound, if one is defined.
28
+ attr_reader :lower_bound
29
+
30
+ # @return [String] a URL describing the unit for this quantity, e.g. "meter", "kilometer", "pound", "chapter", "section", etc.
31
+ attr_reader :unit
32
+
33
+ # @param amount [String]
34
+ # @param upper_bound [String]
35
+ # @param lower_bound [String]
36
+ # @param unit [String]
37
+ # @return [void]
38
+ def initialize(amount:, upper_bound:, lower_bound:, unit:)
39
+ @amount = amount
40
+ @upper_bound = upper_bound
41
+ @lower_bound = lower_bound
42
+ @unit = unit
43
+ end
44
+
45
+ # @return [Hash]
46
+ def to_h
47
+ {
48
+ amount: @amount,
49
+ upper_bound: @upper_bound,
50
+ lower_bound: @lower_bound,
51
+ unit: @unit
52
+ }
53
+ end
54
+
55
+ # The "type" value used by Wikibase, for use when creating/updating statements.
56
+ #
57
+ # @return [String]
58
+ def wikibase_type
59
+ 'quantity'
60
+ end
61
+
62
+ # The "datatype" value used by Wikibase, usually identical to wikibase_type
63
+ # but not always.
64
+ #
65
+ # @return [String]
66
+ def wikibase_datatype
67
+ wikibase_type
68
+ end
69
+
70
+ # @!visibility private
71
+ def self.marshal_load(data_value_json)
72
+ Wikidatum::DataValueType::Base.new(
73
+ type: :quantity,
74
+ value: new(
75
+ amount: data_value_json['amount'],
76
+ upper_bound: data_value_json['upperBound'],
77
+ lower_bound: data_value_json['lowerBound'],
78
+ unit: data_value_json['unit']
79
+ )
80
+ )
81
+ end
82
+
83
+ # @!visibility private
84
+ def marshal_dump
85
+ {
86
+ amount: @amount,
87
+ upperBound: @upper_bound,
88
+ lowerBound: @lower_bound,
89
+ unit: @unit
90
+ }
91
+ end
92
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_value_type/base'
4
+
5
+ # The SomeValue type actually has no datavalue key in the blob at all. We work
6
+ # around this by just passing nil to the serializer.
7
+
8
+ # Represents a value of "unknown value".
9
+ class Wikidatum::DataValueType::SomeValue < Wikidatum::DataValueType::Base
10
+ # The "type" value used by Wikibase, for use when creating/updating statements.
11
+ #
12
+ # @return [String]
13
+ def wikibase_type
14
+ 'string'
15
+ end
16
+
17
+ # The "datatype" value used by Wikibase, usually identical to wikibase_type
18
+ # but not always.
19
+ #
20
+ # @return [String]
21
+ def wikibase_datatype
22
+ wikibase_type
23
+ end
24
+
25
+ # @!visibility private
26
+ def self.marshal_load(_data_value_json)
27
+ new(type: :some_value, value: nil)
28
+ end
29
+ end
@@ -0,0 +1,187 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_value_type/base'
4
+
5
+ # The time type datavalue JSON looks like this:
6
+ #
7
+ # ```json
8
+ # {
9
+ # "datavalue": {
10
+ # "value": {
11
+ # "time": "+2019-11-14T00:00:00Z",
12
+ # "timezone": 0,
13
+ # "before": 0,
14
+ # "after": 0,
15
+ # "precision": 11,
16
+ # "calendarmodel": "http://www.wikidata.org/entity/Q1985727"
17
+ # },
18
+ # "type": "time"
19
+ # }
20
+ # }
21
+ # ```
22
+ #
23
+ # We do not include before and after because the documentation states that
24
+ # they're unused and "may be removed in the future".
25
+ #
26
+ # NOTE: For consistency with Ruby snake_case attribute names, `timezone` from
27
+ # the API is represented as `time_zone` and `calendarmodel` is
28
+ # `calendar_model`. However, we expose aliases so `timezone` and
29
+ # `calendarmodel` will still work.
30
+ class Wikidatum::DataValueType::Time
31
+ # A string representing the time in a format that is very similar to ISO 8601.
32
+ #
33
+ # For example, here are what dates look like for the most common precisions:
34
+ #
35
+ # - years (9): "+2022-00-00T00:00:00Z", meaning "2022"
36
+ # - months (10): "+2022-03-00T00:00:00Z", meaning "March 2022"
37
+ # - days (11): "+2022-01-01T00:00:00Z", meaning "January 1, 2022"
38
+ #
39
+ # NOTE: Due to how precision works, it's probably not a good idea to use the
40
+ # Ruby `Date` or `Time` classes to parse these values unless it's a day-level
41
+ # precision. `Date.parse` will error if you give it a string like
42
+ # "2022-00-00", but it'll handle "2022-01-01" fine. `Time.new` will parse
43
+ # "2022-00-00" as January 1, 2022. There are various other pitfalls that make
44
+ # this generally dangerous unless you're very careful, which is why Wikidatum
45
+ # just handles the time as a string and leaves it to end-users to do what they
46
+ # like with it.
47
+ #
48
+ # @return [String] the time value, in a format like "+2022-01-01T00:00:00Z", though how this should be interpreted depends on the precision.
49
+ attr_reader :time
50
+
51
+ # @return [Integer] an integer for the offset (in minutes) from UTC. 0 means
52
+ # UTC, will currently always be 0 but the Wikibase backend may change that
53
+ # in the future.
54
+ attr_reader :time_zone
55
+
56
+ # An integer representing the precision of the date, where the integers correspond to the following:
57
+ #
58
+ # - 0: 1 Gigayear
59
+ # - 1: 100 Megayears
60
+ # - 2: 10 Megayears
61
+ # - 3: Megayear
62
+ # - 4: 100 Kiloyears
63
+ # - 5: 10 Kiloyears
64
+ # - 6: millennium
65
+ # - 7: century
66
+ # - 8: 10 years
67
+ # - 9: years
68
+ # - 10: months
69
+ # - 11: days
70
+ # - 12: hours (unused)
71
+ # - 13: minutes (unused)
72
+ # - 14: seconds (unused)
73
+ #
74
+ # Usually only 9, 10, and 11 are used in actual items, though for some items
75
+ # you'll need to handle the other cases.
76
+ #
77
+ # For example, the date August 12, 2022 (aka "2022-08-12") would have a
78
+ # precision of days (11).
79
+ #
80
+ # If the time represented is August 2022 because the value is only precise
81
+ # to the month (e.g. a person who's birth is only known to the month rather
82
+ # than the exact day) that would have a precision of months (10).
83
+ #
84
+ # If the time represented is "2022" because it's only precise to the year,
85
+ # that would have a precision of years (9).
86
+ #
87
+ # @return [Integer]
88
+ attr_reader :precision
89
+
90
+ # @return [String] a URL (usually in the same Wikibase instance) representing the given calendar model (e.g. Gregorian, Julian).
91
+ attr_reader :calendar_model
92
+
93
+ # @param time [String]
94
+ # @param time_zone [Integer]
95
+ # @param precision [Integer]
96
+ # @param calendar_model [String]
97
+ # @return [void]
98
+ def initialize(time:, time_zone:, precision:, calendar_model:)
99
+ @time = time
100
+ @time_zone = time_zone
101
+ @precision = precision
102
+ @calendar_model = calendar_model
103
+ end
104
+
105
+ # @return [Hash]
106
+ def to_h
107
+ {
108
+ time: @time,
109
+ time_zone: @time_zone,
110
+ precision: @precision,
111
+ pretty_precision: pretty_precision,
112
+ calendar_model: @calendar_model
113
+ }
114
+ end
115
+
116
+ # The "type" value used by Wikibase, for use when creating/updating statements.
117
+ #
118
+ # @return [String]
119
+ def wikibase_type
120
+ 'time'
121
+ end
122
+
123
+ # The "datatype" value used by Wikibase, usually identical to wikibase_type
124
+ # but not always.
125
+ #
126
+ # @return [String]
127
+ def wikibase_datatype
128
+ wikibase_type
129
+ end
130
+
131
+ # @!visibility private
132
+ def self.marshal_load(data_value_json)
133
+ Wikidatum::DataValueType::Base.new(
134
+ type: :time,
135
+ value: new(
136
+ time: data_value_json['time'],
137
+ time_zone: data_value_json['timezone'],
138
+ precision: data_value_json['precision'],
139
+ calendar_model: data_value_json['calendarmodel']
140
+ )
141
+ )
142
+ end
143
+
144
+ # @!visibility private
145
+ def marshal_dump
146
+ {
147
+ time: @time,
148
+ timezone: @time_zone,
149
+ precision: @precision,
150
+ calendarmodel: @calendar_model
151
+ }
152
+ end
153
+
154
+ PRETTY_PRECISIONS = {
155
+ 0 => :gigayear,
156
+ 1 => :'100_megayear',
157
+ 2 => :'10_megayear',
158
+ 3 => :megayear,
159
+ 4 => :'100_kiloyear',
160
+ 5 => :'10_kiloyear',
161
+ 6 => :millennium,
162
+ 7 => :century,
163
+ 8 => :decade,
164
+ 9 => :year,
165
+ 10 => :month,
166
+ 11 => :day,
167
+ 12 => :hour,
168
+ 13 => :minute,
169
+ 14 => :second
170
+ }.freeze
171
+
172
+ # Returns a symbol representation of the precision, in singular form.
173
+ #
174
+ # Possible values are `:gigayear`, `:'100_megayear'`, `:'10_megayear'`,
175
+ # `:megayear`, `:'100_kiloyear'`, `:'10_kiloyear'`, `:millennium`, `:century`,
176
+ # `:decade`, `:year`, `:month`, `:day`, `:hour`, `:minute`, and `:second`.
177
+ #
178
+ # @return [Symbol]
179
+ def pretty_precision
180
+ PRETTY_PRECISIONS[@precision]
181
+ end
182
+
183
+ # Aliases to match the name returned by the REST API.
184
+
185
+ alias timezone time_zone
186
+ alias calendarmodel calendar_model
187
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_value_type/base'
4
+
5
+ # The Wikibase Entity ID type datavalue JSON looks like this:
6
+ #
7
+ # ```json
8
+ # {
9
+ # "datavalue": {
10
+ # "value": {
11
+ # "entity-type": "item",
12
+ # "numeric-id": 552863,
13
+ # "id": "Q552863"
14
+ # },
15
+ # "type": "wikibase-entityid"
16
+ # }
17
+ # }
18
+ # ```
19
+ class Wikidatum::DataValueType::WikibaseEntityId
20
+ # @return [String] usually "item"
21
+ attr_reader :entity_type
22
+
23
+ # @return [Integer] the integer representation of the Wikibase ID.
24
+ attr_reader :numeric_id
25
+
26
+ # @return [String] in the format "Q123".
27
+ attr_reader :id
28
+
29
+ # @param entity_type [String]
30
+ # @param numeric_id [Integer]
31
+ # @param id [String]
32
+ # @return [void]
33
+ def initialize(entity_type:, numeric_id:, id:)
34
+ @entity_type = entity_type
35
+ @numeric_id = numeric_id
36
+ @id = id
37
+ end
38
+
39
+ # @return [Hash]
40
+ def to_h
41
+ {
42
+ entity_type: @entity_type,
43
+ numeric_id: @numeric_id,
44
+ id: @id
45
+ }
46
+ end
47
+
48
+ # The "type" value used by Wikibase, for use when creating/updating statements.
49
+ #
50
+ # @return [String]
51
+ def wikibase_type
52
+ 'wikibase-entityid'
53
+ end
54
+
55
+ # The "datatype" value used by Wikibase, usually identical to wikibase_type
56
+ # but not always.
57
+ #
58
+ # @return [String]
59
+ def wikibase_datatype
60
+ 'wikibase-item' # yes, really
61
+ end
62
+
63
+ # @!visibility private
64
+ def self.marshal_load(data_value_json)
65
+ Wikidatum::DataValueType::Base.new(
66
+ type: :wikibase_entity_id,
67
+ value: new(
68
+ entity_type: data_value_json['entity-type'],
69
+ numeric_id: data_value_json['numeric-id'],
70
+ id: data_value_json['id']
71
+ )
72
+ )
73
+ end
74
+
75
+ # @!visibility private
76
+ def marshal_dump
77
+ {
78
+ 'entity-type': @entity_type,
79
+ 'numeric-id': @numeric_id,
80
+ id: @id
81
+ }
82
+ end
83
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_value_type/base'
4
+
5
+ # The String type datavalue JSON looks like this:
6
+ #
7
+ # ```json
8
+ # {
9
+ # "datavalue": {
10
+ # "value": "Foobar",
11
+ # "type": "string"
12
+ # }
13
+ # }
14
+ # ```
15
+ class Wikidatum::DataValueType::WikibaseString
16
+ # @return [String] the value for the string.
17
+ attr_reader :string
18
+
19
+ # @param string [String]
20
+ # @return [void]
21
+ def initialize(string:)
22
+ @string = string
23
+ end
24
+
25
+ # @return [Hash]
26
+ def to_h
27
+ {
28
+ string: @string
29
+ }
30
+ end
31
+
32
+ # The "type" value used by Wikibase, for use when creating/updating statements.
33
+ #
34
+ # @return [String]
35
+ def wikibase_type
36
+ 'string'
37
+ end
38
+
39
+ # The "datatype" value used by Wikibase, usually identical to wikibase_type
40
+ # but not always.
41
+ #
42
+ # @return [String]
43
+ def wikibase_datatype
44
+ wikibase_type
45
+ end
46
+
47
+ # @!visibility private
48
+ def self.marshal_load(string)
49
+ Wikidatum::DataValueType::Base.new(
50
+ type: :string,
51
+ value: new(
52
+ string: string
53
+ )
54
+ )
55
+ end
56
+
57
+ # @!visibility private
58
+ def marshal_dump
59
+ @string
60
+ end
61
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_value_type/base'
4
+ require 'wikidatum/data_value_type/globe_coordinate'
5
+ require 'wikidatum/data_value_type/monolingual_text'
6
+ require 'wikidatum/data_value_type/no_value'
7
+ require 'wikidatum/data_value_type/quantity'
8
+ require 'wikidatum/data_value_type/some_value'
9
+ require 'wikidatum/data_value_type/time'
10
+ require 'wikidatum/data_value_type/wikibase_entity_id'
11
+ require 'wikidatum/data_value_type/wikibase_string'