rbrainz 0.1.1 → 0.2.0
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.
- data/CHANGES +31 -0
- data/LICENSE +1 -1
- data/README +3 -2
- data/Rakefile +40 -22
- data/TODO +6 -23
- data/doc/README.rdoc +50 -21
- data/examples/getartist.rb +6 -4
- data/examples/getuser.rb +30 -0
- data/examples/searchartists.rb +35 -0
- data/lib/rbrainz.rb +12 -7
- data/lib/rbrainz/core_ext.rb +8 -0
- data/lib/rbrainz/core_ext/mbid.rb +30 -0
- data/lib/rbrainz/core_ext/net_http_digest.rb +52 -0
- data/lib/rbrainz/core_ext/range.rb +28 -0
- data/lib/rbrainz/core_ext/range/equality.rb +232 -0
- data/lib/rbrainz/data/countrynames.rb +7 -5
- data/lib/rbrainz/data/languagenames.rb +8 -5
- data/lib/rbrainz/data/releasetypenames.rb +34 -0
- data/lib/rbrainz/data/scriptnames.rb +8 -5
- data/lib/rbrainz/model.rb +27 -35
- data/lib/rbrainz/model/alias.rb +31 -7
- data/lib/rbrainz/model/artist.rb +30 -41
- data/lib/rbrainz/model/collection.rb +102 -0
- data/lib/rbrainz/model/default_factory.rb +78 -0
- data/lib/rbrainz/model/disc.rb +45 -8
- data/lib/rbrainz/model/entity.rb +122 -53
- data/lib/rbrainz/model/incomplete_date.rb +31 -47
- data/lib/rbrainz/model/individual.rb +103 -0
- data/lib/rbrainz/model/label.rb +42 -33
- data/lib/rbrainz/model/mbid.rb +111 -40
- data/lib/rbrainz/model/relation.rb +78 -14
- data/lib/rbrainz/model/release.rb +119 -31
- data/lib/rbrainz/model/release_event.rb +38 -9
- data/lib/rbrainz/model/scored_collection.rb +99 -0
- data/lib/rbrainz/model/tag.rb +39 -0
- data/lib/rbrainz/model/track.rb +37 -13
- data/lib/rbrainz/model/user.rb +48 -0
- data/lib/rbrainz/utils.rb +9 -0
- data/lib/rbrainz/utils/data.rb +78 -0
- data/lib/rbrainz/utils/helper.rb +22 -0
- data/lib/rbrainz/version.rb +15 -0
- data/lib/rbrainz/webservice.rb +32 -6
- data/lib/rbrainz/webservice/filter.rb +124 -47
- data/lib/rbrainz/webservice/includes.rb +49 -10
- data/lib/rbrainz/webservice/mbxml.rb +228 -173
- data/lib/rbrainz/webservice/query.rb +312 -25
- data/lib/rbrainz/webservice/webservice.rb +164 -27
- data/test/lib/mock_webservice.rb +53 -0
- data/test/lib/test_entity.rb +27 -8
- data/test/lib/test_factory.rb +47 -0
- data/test/lib/testing_helper.rb +7 -5
- data/test/test-data/invalid/artist/tags_1.xml +6 -0
- data/test/test-data/valid/artist/Tchaikovsky-2.xml +12 -0
- data/test/test-data/valid/label/Atlantic_Records_2.xml +3 -0
- data/test/test-data/valid/label/Atlantic_Records_3.xml +11 -0
- data/test/test-data/valid/release/Highway_61_Revisited_2.xml +12 -0
- data/test/test-data/valid/track/Silent_All_These_Years_6.xml +8 -0
- data/test/test_alias.rb +13 -7
- data/test/test_artist.rb +26 -4
- data/test/test_artist_filter.rb +11 -6
- data/test/test_artist_includes.rb +11 -6
- data/test/test_collection.rb +66 -0
- data/test/test_default_factory.rb +75 -0
- data/test/test_disc.rb +9 -4
- data/test/test_incomplete_date.rb +21 -14
- data/test/test_label.rb +56 -18
- data/test/test_label_filter.rb +10 -5
- data/test/test_label_includes.rb +11 -6
- data/test/test_mbid.rb +34 -19
- data/test/test_mbxml.rb +242 -72
- data/test/test_query.rb +92 -7
- data/test/test_range_equality.rb +144 -0
- data/test/test_relation.rb +18 -7
- data/test/test_release.rb +15 -4
- data/test/test_release_event.rb +16 -4
- data/test/test_release_filter.rb +11 -5
- data/test/test_release_includes.rb +11 -6
- data/test/test_scored_collection.rb +86 -0
- data/test/test_tag.rb +39 -0
- data/test/test_track.rb +15 -4
- data/test/test_track_filter.rb +11 -5
- data/test/test_track_includes.rb +11 -6
- data/test/test_utils.rb +41 -0
- data/test/test_webservice.rb +16 -17
- metadata +93 -57
@@ -1,17 +1,19 @@
|
|
1
|
-
# $Id: mbxml.rb
|
2
|
-
#
|
3
|
-
#
|
4
|
-
#
|
1
|
+
# $Id: mbxml.rb 148 2007-07-19 17:26:33Z phw $
|
2
|
+
#
|
3
|
+
# Author:: Philipp Wolfer (mailto:phw@rubyforge.org)
|
4
|
+
# Copyright:: Copyright (c) 2007, Nigel Graham, Philipp Wolfer
|
5
|
+
# License:: RBrainz is free software distributed under a BSD style license.
|
6
|
+
# See LICENSE[file:../LICENSE.html] for permissions.
|
5
7
|
|
6
8
|
require 'rbrainz/model'
|
9
|
+
require 'rbrainz/model/scored_collection'
|
7
10
|
require 'rexml/document'
|
8
|
-
include REXML
|
9
11
|
|
10
12
|
module MusicBrainz
|
11
13
|
module Webservice
|
12
14
|
|
13
15
|
# Class to read the XML data returned by the MusicBrainz
|
14
|
-
#
|
16
|
+
# web service and create the corresponding model classes.
|
15
17
|
# The class understands the MusicBrainz XML Metadata Version 1.0
|
16
18
|
# schema.
|
17
19
|
#
|
@@ -19,12 +21,31 @@ module MusicBrainz
|
|
19
21
|
# information on the MusicBrainz XML Metadata schema.
|
20
22
|
class MBXML
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
+
# Exception to be raised if a parse error occurs in MBXML.
|
25
|
+
class ParseError < Exception
|
26
|
+
end
|
27
|
+
|
28
|
+
# Create a new MBXML instance to parse a MusicBrainz metadata document.
|
29
|
+
#
|
30
|
+
# Parameters:
|
31
|
+
# [stream] An IO object to read the MusicBrainz metadata XML document from.
|
32
|
+
# [factory] A model factory. An instance of Model::DefaultFactory
|
33
|
+
# will be used if none is given.
|
34
|
+
#
|
35
|
+
# Raises:: MBXML::ParseError
|
36
|
+
def initialize(stream, factory=nil)
|
37
|
+
begin
|
38
|
+
@document = REXML::Document.new(stream)
|
39
|
+
rescue REXML::ParseException => e
|
40
|
+
raise ParseError.new(e.to_s)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Set the model factory
|
44
|
+
factory = Model::DefaultFactory.new unless factory
|
45
|
+
@factory = factory
|
24
46
|
|
25
|
-
# Already loaded artists, releases, tracks
|
26
|
-
#
|
27
|
-
# to link to them if they occure multiple times
|
47
|
+
# Already loaded artists, releases, tracks and labels will get cached
|
48
|
+
# in these variables to link to them if they occure multiple times
|
28
49
|
# inside the same document.
|
29
50
|
@artists = Hash.new
|
30
51
|
@releases = Hash.new
|
@@ -32,9 +53,9 @@ module MusicBrainz
|
|
32
53
|
@labels = Hash.new
|
33
54
|
end
|
34
55
|
|
35
|
-
# Read the XML string and create an entity model
|
36
|
-
#
|
37
|
-
#
|
56
|
+
# Read the XML string and create an entity model for the given entity
|
57
|
+
# type if it is present in the document.
|
58
|
+
#
|
38
59
|
# Returns nil if no entity of the given type is present.
|
39
60
|
def get_entity(entity_type)
|
40
61
|
# Search for the first occuring node of type entity which is a child node
|
@@ -43,80 +64,53 @@ module MusicBrainz
|
|
43
64
|
[Model::NS_MMD_1, entity_type]]
|
44
65
|
|
45
66
|
unless entity.nil? or entity.is_a? REXML::Text
|
46
|
-
|
47
|
-
|
48
|
-
return create_artist(entity)
|
49
|
-
when 'release'
|
50
|
-
return create_release(entity)
|
51
|
-
when 'track'
|
52
|
-
return create_track(entity)
|
53
|
-
when 'label'
|
54
|
-
return create_label(entity)
|
55
|
-
end
|
67
|
+
create_method = method('create_' + entity.name)
|
68
|
+
create_method.call(entity) if create_method
|
56
69
|
else
|
57
70
|
return nil
|
58
71
|
end
|
59
72
|
end
|
60
73
|
|
61
|
-
# Read the XML string and create a list of entity
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
# Returns
|
66
|
-
#
|
67
|
-
|
74
|
+
# Read the XML string and create a list of entity models for the given
|
75
|
+
# entity type. There must be an entity-list element as a child of the
|
76
|
+
# +metadata+ element in the document.
|
77
|
+
#
|
78
|
+
# Returns an empty Collection if the list is empty.
|
79
|
+
# Raises a MBXML::ParseError if no entity-list element can be found.
|
80
|
+
#
|
81
|
+
# Raises:: MBXML::ParseError
|
82
|
+
def get_entity_list(entity_type, ns=Model::NS_MMD_1)
|
68
83
|
# Search for the first occuring node of type entity which is a child node
|
69
84
|
# of the metadata element.
|
70
|
-
entity_list = @document.elements[
|
71
|
-
|
85
|
+
entity_list = @document.elements[
|
86
|
+
"//[local-name()='metadata' and namespace-uri()='%s']/[local-name()='%s-list' and namespace-uri()='%s'][1]" %
|
87
|
+
[Model::NS_MMD_1, entity_type, ns]]
|
72
88
|
|
73
89
|
unless entity_list.nil? or entity_list.is_a? REXML::Text
|
74
|
-
|
90
|
+
collection = Model::ScoredCollection.new(entity_list.attributes['count'],
|
91
|
+
entity_list.attributes['offset'])
|
92
|
+
# Select the method to use for reading the list.
|
93
|
+
read_list_method = method('read_' + entity_list.name.gsub('-', '_'))
|
75
94
|
|
76
|
-
|
77
|
-
|
78
|
-
read_artist_list(entity_list) {|model|
|
79
|
-
list << model
|
80
|
-
}
|
81
|
-
return list
|
82
|
-
when 'release-list'
|
83
|
-
read_release_list(entity_list) {|model|
|
84
|
-
list << model
|
85
|
-
}
|
86
|
-
return list
|
87
|
-
when 'track-list'
|
88
|
-
read_track_list(entity_list) {|model|
|
89
|
-
list << model
|
90
|
-
}
|
91
|
-
return list
|
92
|
-
when 'label-list'
|
93
|
-
read_label_list(entity_list) {|model|
|
94
|
-
list << model
|
95
|
-
}
|
96
|
-
return list
|
97
|
-
end
|
95
|
+
# Read the entity list and store the entities in the collection.
|
96
|
+
read_list_method.call(entity_list, collection, true) if read_list_method
|
98
97
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
raise model.inspect
|
103
|
-
list << model
|
104
|
-
}
|
105
|
-
return list
|
106
|
-
end
|
98
|
+
return collection
|
99
|
+
else
|
100
|
+
raise ParseError.new("no element %s-list found" % entity_type)
|
107
101
|
end
|
108
102
|
return nil
|
109
103
|
end
|
110
104
|
|
111
105
|
private # ----------------------------------------------------------------
|
112
106
|
|
113
|
-
# Iterate over a list of artists.
|
107
|
+
# Iterate over a list of artists and add them to the target collection.
|
114
108
|
#
|
115
109
|
# The node must be of the type <em>artist-list</em>.
|
116
|
-
def read_artist_list(
|
117
|
-
|
118
|
-
yield
|
119
|
-
|
110
|
+
def read_artist_list(list_node, target_collection, read_scores=false)
|
111
|
+
read_list(list_node, target_collection, 'artist', read_scores) do |a|
|
112
|
+
yield a if block_given?
|
113
|
+
end
|
120
114
|
end
|
121
115
|
|
122
116
|
# Create an +Artist+ object from the given artist node.
|
@@ -124,7 +118,7 @@ module MusicBrainz
|
|
124
118
|
if node.attributes['id'] and @artists[node.attributes['id']]
|
125
119
|
artist = @artists[node.attributes['id']]
|
126
120
|
else
|
127
|
-
artist =
|
121
|
+
artist = @factory.new_artist
|
128
122
|
@artists[node.attributes['id']] = artist
|
129
123
|
end
|
130
124
|
|
@@ -148,19 +142,12 @@ module MusicBrainz
|
|
148
142
|
end
|
149
143
|
|
150
144
|
# Read the alias list
|
151
|
-
|
152
|
-
read_alias_list(node.elements['alias-list']) {|artist_alias|
|
153
|
-
artist.aliases << artist_alias
|
154
|
-
}
|
155
|
-
end
|
145
|
+
read_alias_list(node.elements['alias-list'], artist.aliases)
|
156
146
|
|
157
147
|
# Read the release list
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
artist.releases << release
|
162
|
-
}
|
163
|
-
end
|
148
|
+
read_release_list(node.elements['release-list'], artist.releases) {|release|
|
149
|
+
release.artist = artist unless release.artist
|
150
|
+
}
|
164
151
|
|
165
152
|
# Read the relation list
|
166
153
|
if node.elements['relation-list']
|
@@ -171,26 +158,29 @@ module MusicBrainz
|
|
171
158
|
}
|
172
159
|
end
|
173
160
|
|
161
|
+
# Read the tag list
|
162
|
+
read_tag_list(node.elements['tag-list'], artist.tags)
|
163
|
+
|
174
164
|
return artist
|
175
165
|
end
|
176
166
|
|
177
|
-
# Iterate over a list of releases.
|
167
|
+
# Iterate over a list of releases and add them to the target collection.
|
178
168
|
#
|
179
169
|
# The node must be of the type <em>release-list</em>.
|
180
|
-
def read_release_list(
|
181
|
-
|
182
|
-
yield
|
183
|
-
|
170
|
+
def read_release_list(list_node, target_collection, read_scores=false)
|
171
|
+
read_list(list_node, target_collection, 'release', read_scores) do |a|
|
172
|
+
yield a if block_given?
|
173
|
+
end
|
184
174
|
end
|
185
175
|
|
186
176
|
# Create a +Release+ object from the given release node.
|
187
177
|
#
|
188
|
-
# TODO
|
178
|
+
# TODO:: PUID list
|
189
179
|
def create_release(node)
|
190
180
|
if node.attributes['id'] and @releases[node.attributes['id']]
|
191
181
|
release = @releases[node.attributes['id']]
|
192
182
|
else
|
193
|
-
release =
|
183
|
+
release = @factory.new_release
|
194
184
|
@releases[node.attributes['id']] = release
|
195
185
|
end
|
196
186
|
|
@@ -212,28 +202,17 @@ module MusicBrainz
|
|
212
202
|
end
|
213
203
|
|
214
204
|
# Read the track list
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
release.tracks << track
|
220
|
-
}
|
221
|
-
end
|
205
|
+
read_track_list(node.elements['track-list'], release.tracks) {|track|
|
206
|
+
track.artist = release.artist unless track.artist
|
207
|
+
track.releases << release
|
208
|
+
}
|
222
209
|
|
223
210
|
# Read the release event list
|
224
|
-
|
225
|
-
read_release_event_list(node.elements['release-event-list']) {|event|
|
226
|
-
release.release_events << event
|
227
|
-
}
|
228
|
-
end
|
211
|
+
read_release_event_list(node.elements['release-event-list'], release.release_events)
|
229
212
|
|
230
213
|
# Read the disc list
|
231
|
-
|
232
|
-
|
233
|
-
release.discs << disc
|
234
|
-
}
|
235
|
-
end
|
236
|
-
|
214
|
+
read_disc_list(node.elements['disc-list'], release.discs)
|
215
|
+
|
237
216
|
# Read the relation list
|
238
217
|
if node.elements['relation-list']
|
239
218
|
node.elements.each('relation-list') {|relation_node|
|
@@ -243,16 +222,19 @@ module MusicBrainz
|
|
243
222
|
}
|
244
223
|
end
|
245
224
|
|
225
|
+
# Read the tag list
|
226
|
+
read_tag_list(node.elements['tag-list'], release.tags)
|
227
|
+
|
246
228
|
return release
|
247
229
|
end
|
248
230
|
|
249
|
-
# Iterate over a list of tracks.
|
231
|
+
# Iterate over a list of tracks and add them to the target collection.
|
250
232
|
#
|
251
233
|
# The node must be of the type <em>track-list</em>.
|
252
|
-
def read_track_list(
|
253
|
-
|
254
|
-
yield
|
255
|
-
|
234
|
+
def read_track_list(list_node, target_collection, read_scores=false)
|
235
|
+
read_list(list_node, target_collection, 'track', read_scores) do |a|
|
236
|
+
yield a if block_given?
|
237
|
+
end
|
256
238
|
end
|
257
239
|
|
258
240
|
# Create a +Track+ object from the given track node.
|
@@ -260,7 +242,7 @@ module MusicBrainz
|
|
260
242
|
if node.attributes['id'] and @tracks[node.attributes['id']]
|
261
243
|
track = @tracks[node.attributes['id']]
|
262
244
|
else
|
263
|
-
track =
|
245
|
+
track = @factory.new_track
|
264
246
|
@tracks[node.attributes['id']] = track
|
265
247
|
end
|
266
248
|
|
@@ -271,19 +253,12 @@ module MusicBrainz
|
|
271
253
|
track.artist = create_artist(node.elements['artist']) if node.elements['artist']
|
272
254
|
|
273
255
|
# Read the release list
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
track.releases << release
|
278
|
-
}
|
279
|
-
end
|
256
|
+
read_release_list(node.elements['release-list'], track.releases) {|release|
|
257
|
+
release.tracks << track
|
258
|
+
}
|
280
259
|
|
281
260
|
# Read the PUID list
|
282
|
-
|
283
|
-
read_puid_list(node.elements['puid-list']) {|puid|
|
284
|
-
track.puids << puid
|
285
|
-
}
|
286
|
-
end
|
261
|
+
read_puid_list(node.elements['puid-list'], track.puids)
|
287
262
|
|
288
263
|
# Read the relation list
|
289
264
|
if node.elements['relation-list']
|
@@ -294,16 +269,19 @@ module MusicBrainz
|
|
294
269
|
}
|
295
270
|
end
|
296
271
|
|
272
|
+
# Read the tag list
|
273
|
+
read_tag_list(node.elements['tag-list'], track.tags)
|
274
|
+
|
297
275
|
return track
|
298
276
|
end
|
299
277
|
|
300
|
-
# Iterate over a list of labels.
|
278
|
+
# Iterate over a list of labels and add them to the target collection.
|
301
279
|
#
|
302
280
|
# The node must be of the type <em>label-list</em>.
|
303
|
-
def read_label_list(
|
304
|
-
|
305
|
-
yield
|
306
|
-
|
281
|
+
def read_label_list(list_node, target_collection, read_scores=false)
|
282
|
+
read_list(list_node, target_collection, 'label', read_scores) do |a|
|
283
|
+
yield a if block_given?
|
284
|
+
end
|
307
285
|
end
|
308
286
|
|
309
287
|
# Create a +Label+ object from the given label node.
|
@@ -311,7 +289,7 @@ module MusicBrainz
|
|
311
289
|
if node.attributes['id'] and @labels[node.attributes['id']]
|
312
290
|
label = @labels[node.attributes['id']]
|
313
291
|
else
|
314
|
-
label =
|
292
|
+
label = @factory.new_label
|
315
293
|
@labels[node.attributes['id']] = label
|
316
294
|
end
|
317
295
|
|
@@ -329,19 +307,18 @@ module MusicBrainz
|
|
329
307
|
|
330
308
|
if life_span = node.elements['life-span']
|
331
309
|
if life_span.attributes['begin']
|
332
|
-
label.
|
310
|
+
label.begin_date = Model::IncompleteDate.new life_span.attributes['begin']
|
333
311
|
end
|
334
312
|
if life_span.attributes['end']
|
335
|
-
label.
|
313
|
+
label.end_date = Model::IncompleteDate.new life_span.attributes['end']
|
336
314
|
end
|
337
315
|
end
|
338
316
|
|
339
317
|
# Read the alias list
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
end
|
318
|
+
read_alias_list(node.elements['alias-list'], label.aliases)
|
319
|
+
|
320
|
+
# Read the release list
|
321
|
+
read_release_list(node.elements['release-list'], label.releases)
|
345
322
|
|
346
323
|
# Read the relation list
|
347
324
|
if node.elements['relation-list']
|
@@ -352,39 +329,61 @@ module MusicBrainz
|
|
352
329
|
}
|
353
330
|
end
|
354
331
|
|
332
|
+
# Read the tag list
|
333
|
+
read_tag_list(node.elements['tag-list'], label.tags)
|
334
|
+
|
355
335
|
return label
|
356
336
|
end
|
357
337
|
|
358
|
-
# Iterate over a list of aliases.
|
338
|
+
# Iterate over a list of aliases and add them to the target collection.
|
359
339
|
#
|
360
340
|
# The node must be of the type <em>alias-list</em>.
|
361
|
-
def read_alias_list(
|
362
|
-
|
363
|
-
yield
|
364
|
-
|
341
|
+
def read_alias_list(list_node, target_collection)
|
342
|
+
read_list(list_node, target_collection, 'alias') do |a|
|
343
|
+
yield a if block_given?
|
344
|
+
end
|
365
345
|
end
|
366
346
|
|
367
347
|
# Create an +Alias+ object from the given alias node.
|
368
348
|
def create_alias(node)
|
369
|
-
alias_model =
|
349
|
+
alias_model = @factory.new_alias
|
370
350
|
alias_model.name = node.text
|
371
|
-
|
351
|
+
if node.attributes['type']
|
352
|
+
alias_model.type = MBXML.add_namespace(node.attributes['type'], Model::NS_MMD_1)
|
353
|
+
end
|
372
354
|
alias_model.script = node.attributes['script']
|
373
355
|
return alias_model
|
374
356
|
end
|
375
357
|
|
376
|
-
# Iterate over a list of
|
358
|
+
# Iterate over a list of tags and add them to the target collection.
|
359
|
+
#
|
360
|
+
# The node must be of the type <em>tag-list</em>.
|
361
|
+
def read_tag_list(list_node, target_collection)
|
362
|
+
read_list(list_node, target_collection, 'tag') do |a|
|
363
|
+
yield a if block_given?
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
# Create an +Tag+ object from the given tag node.
|
368
|
+
def create_tag(node)
|
369
|
+
tag = @factory.new_tag
|
370
|
+
tag.text = node.text
|
371
|
+
tag.count = node.attributes['count'].to_i if node.attributes['count']
|
372
|
+
return tag
|
373
|
+
end
|
374
|
+
|
375
|
+
# Iterate over a list of release events and add them to the target collection.
|
377
376
|
#
|
378
377
|
# The node must be of the type <em>release-event-list</em>.
|
379
|
-
def read_release_event_list(
|
380
|
-
|
381
|
-
yield
|
382
|
-
|
378
|
+
def read_release_event_list(list_node, target_collection)
|
379
|
+
read_list(list_node, target_collection, 'event') do |a|
|
380
|
+
yield a if block_given?
|
381
|
+
end
|
383
382
|
end
|
384
383
|
|
385
384
|
# Create an +ReleaseEvent+ object from the given release event node.
|
386
|
-
def
|
387
|
-
event =
|
385
|
+
def create_event(node)
|
386
|
+
event = @factory.new_release_event
|
388
387
|
|
389
388
|
# Read all defined data fields
|
390
389
|
if node.attributes['date']
|
@@ -398,40 +397,50 @@ module MusicBrainz
|
|
398
397
|
return event
|
399
398
|
end
|
400
399
|
|
401
|
-
# Iterate over a list of PUIDs.
|
400
|
+
# Iterate over a list of PUIDs and add them to the target collection.
|
402
401
|
#
|
403
402
|
# The node must be of the type <em>puid-list</em>.
|
404
|
-
def read_puid_list(
|
405
|
-
|
406
|
-
yield
|
407
|
-
|
403
|
+
def read_puid_list(list_node, target_collection)
|
404
|
+
read_list(list_node, target_collection, 'puid') do |a|
|
405
|
+
yield a if block_given?
|
406
|
+
end
|
408
407
|
end
|
409
408
|
|
410
|
-
#
|
409
|
+
# Create a PUID
|
410
|
+
def create_puid(node)
|
411
|
+
return node.attributes['id']
|
412
|
+
end
|
413
|
+
|
414
|
+
# Iterate over a list of discs and add them to the target collection.
|
411
415
|
#
|
412
416
|
# The node must be of the type <em>disc-list</em>.
|
413
|
-
def read_disc_list(
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
417
|
+
def read_disc_list(list_node, target_collection)
|
418
|
+
read_list(list_node, target_collection, 'disc') do |a|
|
419
|
+
yield a if block_given?
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
# Create a +Disc+ object from the given disc node.
|
424
|
+
def create_disc(node)
|
425
|
+
disc = @factory.new_disc
|
426
|
+
disc.id = node.attributes['id']
|
427
|
+
disc.sectors = node.attributes['sectors'].to_i
|
428
|
+
return disc
|
420
429
|
end
|
421
430
|
|
422
431
|
# Iterate over a list of relations.
|
423
432
|
#
|
424
433
|
# The node must be of the type <em>relation-list</em>.
|
425
434
|
def read_relation_list(node)
|
435
|
+
target_type = MBXML.add_namespace(node.attributes['target-type'], Model::NS_REL_1)
|
426
436
|
node.elements.each('relation') {|child|
|
427
|
-
target_type = MBXML.add_namespace(node.attributes['target-type'], Model::NS_REL_1)
|
428
437
|
yield create_relation(child, target_type)
|
429
438
|
}
|
430
439
|
end
|
431
440
|
|
432
441
|
# Create a +Relation+ object from the given relation node.
|
433
442
|
def create_relation(node, target_type)
|
434
|
-
relation =
|
443
|
+
relation = @factory.new_relation
|
435
444
|
|
436
445
|
# Read all defined data fields
|
437
446
|
if node.attributes['direction']
|
@@ -464,29 +473,29 @@ module MusicBrainz
|
|
464
473
|
if node.elements['artist']
|
465
474
|
target = create_artist node.elements['artist']
|
466
475
|
else
|
467
|
-
target =
|
468
|
-
target.id = Model::MBID.
|
476
|
+
target = @factory.new_artist
|
477
|
+
target.id = Model::MBID.parse(node.attributes['target'], :artist)
|
469
478
|
end
|
470
479
|
when Model::Relation::TO_RELEASE
|
471
480
|
if node.elements['release']
|
472
481
|
target = create_release node.elements['release']
|
473
482
|
else
|
474
|
-
target =
|
475
|
-
target.id = Model::MBID.
|
483
|
+
target = @factory.new_release
|
484
|
+
target.id = Model::MBID.parse(node.attributes['target'], :release)
|
476
485
|
end
|
477
486
|
when Model::Relation::TO_TRACK
|
478
487
|
if node.elements['track']
|
479
488
|
target = create_track node.elements['track']
|
480
489
|
else
|
481
|
-
target =
|
482
|
-
target.id = Model::MBID.
|
490
|
+
target = @factory.new_track
|
491
|
+
target.id = Model::MBID.parse(node.attributes['target'], :track)
|
483
492
|
end
|
484
493
|
when Model::Relation::TO_LABEL
|
485
494
|
if node.elements['label']
|
486
495
|
target = create_label node.elements['label']
|
487
496
|
else
|
488
|
-
target =
|
489
|
-
target.id = Model::MBID.
|
497
|
+
target = @factory.new_label
|
498
|
+
target.id = Model::MBID.parse(node.attributes['target'], :label)
|
490
499
|
end
|
491
500
|
when Model::Relation::TO_URL
|
492
501
|
target = node.attributes['target']
|
@@ -497,6 +506,45 @@ module MusicBrainz
|
|
497
506
|
return relation
|
498
507
|
end
|
499
508
|
|
509
|
+
def read_user_list(list_node, target_collection, read_scores=false)
|
510
|
+
read_list(list_node, target_collection, 'user', read_scores, Model::NS_EXT_1) {|a|
|
511
|
+
yield a if block_given?
|
512
|
+
}
|
513
|
+
end
|
514
|
+
|
515
|
+
def create_user(node)
|
516
|
+
user_model = @factory.new_user
|
517
|
+
# Read the types
|
518
|
+
node.attributes['type'].split(' ').each {|type|
|
519
|
+
user_model.types << MBXML.add_namespace(type, Model::NS_EXT_1)
|
520
|
+
} if node.attributes['type']
|
521
|
+
|
522
|
+
user_model.name = node.elements['name'].text
|
523
|
+
user_model.show_nag = MBXML.get_element(node, 'nag', Model::NS_EXT_1).attributes['show'] == 'true'
|
524
|
+
return user_model
|
525
|
+
end
|
526
|
+
|
527
|
+
# Helper method that reads a list of a special node type.
|
528
|
+
# There must be a method create_{child_name} which returns an
|
529
|
+
# instance of the corresponding model.
|
530
|
+
def read_list(list_node, target_collection, child_name, read_scores=false, ns=Model::NS_MMD_1)
|
531
|
+
if list_node
|
532
|
+
target_collection.offset = list_node.attributes['offset'].to_i
|
533
|
+
target_collection.count = list_node.attributes['count'].to_i
|
534
|
+
MBXML.each_element(list_node, child_name, ns) do |child|
|
535
|
+
model = method('create_' + child_name).call(child)
|
536
|
+
if read_scores
|
537
|
+
score = child.attributes['ext:score'].to_i
|
538
|
+
entry = Model::ScoredCollection::Entry.new(model, score)
|
539
|
+
else
|
540
|
+
entry = model
|
541
|
+
end
|
542
|
+
target_collection << entry
|
543
|
+
yield entry if block_given?
|
544
|
+
end
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
500
548
|
# Helper method which will return the given property
|
501
549
|
# extended by the namespace. If the property
|
502
550
|
# already includes the namespace it will be returned
|
@@ -510,6 +558,13 @@ module MusicBrainz
|
|
510
558
|
end
|
511
559
|
end
|
512
560
|
|
561
|
+
def self.get_element(node, local_name, ns)
|
562
|
+
node.elements["*[local-name() = '#{local_name}' and namespace-uri() = '#{ns}']"]
|
563
|
+
end
|
564
|
+
|
565
|
+
def self.each_element(node, local_name, ns, &block)
|
566
|
+
node.elements.each("*[local-name() = '#{local_name}' and namespace-uri()='#{ns}']", &block)
|
567
|
+
end
|
513
568
|
end
|
514
569
|
|
515
570
|
end
|