rbrainz 0.1.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.
Files changed (84) hide show
  1. data/LICENSE +25 -0
  2. data/README +11 -0
  3. data/Rakefile +110 -0
  4. data/TODO +24 -0
  5. data/doc/README.rdoc +68 -0
  6. data/examples/getartist.rb +54 -0
  7. data/lib/rbrainz.rb +11 -0
  8. data/lib/rbrainz/data/countrynames.rb +259 -0
  9. data/lib/rbrainz/data/languagenames.rb +404 -0
  10. data/lib/rbrainz/data/scriptnames.rb +64 -0
  11. data/lib/rbrainz/model.rb +48 -0
  12. data/lib/rbrainz/model/alias.rb +23 -0
  13. data/lib/rbrainz/model/artist.rb +54 -0
  14. data/lib/rbrainz/model/disc.rb +30 -0
  15. data/lib/rbrainz/model/entity.rb +72 -0
  16. data/lib/rbrainz/model/incomplete_date.rb +76 -0
  17. data/lib/rbrainz/model/label.rb +55 -0
  18. data/lib/rbrainz/model/mbid.rb +82 -0
  19. data/lib/rbrainz/model/release.rb +50 -0
  20. data/lib/rbrainz/model/release_event.rb +34 -0
  21. data/lib/rbrainz/model/track.rb +27 -0
  22. data/lib/rbrainz/webservice.rb +6 -0
  23. data/lib/rbrainz/webservice/filter.rb +132 -0
  24. data/lib/rbrainz/webservice/includes.rb +150 -0
  25. data/lib/rbrainz/webservice/mbxml.rb +404 -0
  26. data/lib/rbrainz/webservice/query.rb +61 -0
  27. data/lib/rbrainz/webservice/webservice.rb +69 -0
  28. data/test/lib/test_entity.rb +58 -0
  29. data/test/lib/testing_helper.rb +13 -0
  30. data/test/test-data/README +13 -0
  31. data/test/test-data/invalid/artist/basic_1.xml +12 -0
  32. data/test/test-data/invalid/artist/basic_2.xml +12 -0
  33. data/test/test-data/invalid/artist/empty_1.xml +0 -0
  34. data/test/test-data/invalid/artist/empty_2.xml +3 -0
  35. data/test/test-data/invalid/artist/empty_3.xml +7 -0
  36. data/test/test-data/invalid/artist/search_result_1.xml +11 -0
  37. data/test/test-data/valid/artist/Tchaikovsky-1.xml +90 -0
  38. data/test/test-data/valid/artist/Tori_Amos_1.xml +8 -0
  39. data/test/test-data/valid/artist/Tori_Amos_2.xml +53 -0
  40. data/test/test-data/valid/artist/Tori_Amos_3.xml +25 -0
  41. data/test/test-data/valid/artist/Tori_Amos_4.xml +14 -0
  42. data/test/test-data/valid/artist/Tori_Amos_5.xml +13 -0
  43. data/test/test-data/valid/artist/empty_1.xml +7 -0
  44. data/test/test-data/valid/artist/empty_2.xml +11 -0
  45. data/test/test-data/valid/artist/search_result_1.xml +19 -0
  46. data/test/test-data/valid/label/Atlantic_Records_1.xml +9 -0
  47. data/test/test-data/valid/label/Atlantic_Records_2.xml +11 -0
  48. data/test/test-data/valid/label/search_result_1.xml +14 -0
  49. data/test/test-data/valid/release/Highway_61_Revisited_1.xml +68 -0
  50. data/test/test-data/valid/release/Little_Earthquakes_1.xml +24 -0
  51. data/test/test-data/valid/release/Little_Earthquakes_2.xml +73 -0
  52. data/test/test-data/valid/release/Mission_Impossible_2.xml +155 -0
  53. data/test/test-data/valid/release/Under_the_Pink_1.xml +16 -0
  54. data/test/test-data/valid/release/Under_the_Pink_2.xml +14 -0
  55. data/test/test-data/valid/release/Under_the_Pink_3.xml +16 -0
  56. data/test/test-data/valid/release/search_result_1.xml +29 -0
  57. data/test/test-data/valid/track/Silent_All_These_Years_1.xml +7 -0
  58. data/test/test-data/valid/track/Silent_All_These_Years_2.xml +21 -0
  59. data/test/test-data/valid/track/Silent_All_These_Years_3.xml +16 -0
  60. data/test/test-data/valid/track/Silent_All_These_Years_4.xml +30 -0
  61. data/test/test-data/valid/track/Silent_All_These_Years_5.xml +20 -0
  62. data/test/test-data/valid/track/search_result_1.xml +45 -0
  63. data/test/test-data/valid/user/User_1.xml +15 -0
  64. data/test/test_alias.rb +50 -0
  65. data/test/test_artist.rb +132 -0
  66. data/test/test_artist_filter.rb +36 -0
  67. data/test/test_artist_includes.rb +63 -0
  68. data/test/test_disc.rb +38 -0
  69. data/test/test_incomplete_date.rb +60 -0
  70. data/test/test_label.rb +129 -0
  71. data/test/test_label_filter.rb +36 -0
  72. data/test/test_label_includes.rb +55 -0
  73. data/test/test_mbid.rb +99 -0
  74. data/test/test_mbxml.rb +368 -0
  75. data/test/test_query.rb +24 -0
  76. data/test/test_release.rb +161 -0
  77. data/test/test_release_event.rb +67 -0
  78. data/test/test_release_filter.rb +57 -0
  79. data/test/test_release_includes.rb +73 -0
  80. data/test/test_track.rb +102 -0
  81. data/test/test_track_filter.rb +57 -0
  82. data/test/test_track_includes.rb +61 -0
  83. data/test/test_webservice.rb +23 -0
  84. metadata +138 -0
@@ -0,0 +1,48 @@
1
+ # $Id: model.rb 13 2007-05-22 22:59:57Z phw $
2
+ # Copyright (c) 2007, Philipp Wolfer
3
+ # All rights reserved.
4
+ # See LICENSE for permissions.
5
+
6
+ module MusicBrainz
7
+ module Model
8
+
9
+ # Namespace for all MusicBrainz metadata.
10
+ NS_MMD_1 = 'http://musicbrainz.org/ns/mmd-1.0#'
11
+
12
+ # Namespace for MusicBrainz relations.
13
+ NS_REL_1 = 'http://musicbrainz.org/ns/rel-1.0#'
14
+
15
+ # Namespace for MusicBrainz extensions.
16
+ NS_EXT_1 = 'http://musicbrainz.org/ns/ext-1.0#'
17
+
18
+ # Defines the format of an UUID (Universally Unique Identifier)
19
+ UUID_REGEXP = /^[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}$/
20
+
21
+ # The format of a MusicBrainz identifier was wrong.
22
+ class InvalidMBIDError < Exception
23
+ end
24
+
25
+ # The format of a MusicBrainz UUID was wrong.
26
+ class InvalidUUIDError < Exception
27
+ end
28
+
29
+ # An unknown entity was encountered.
30
+ # Valid entities are only :artist, :release, :track and :label.
31
+ class UnknownEntityError < Exception
32
+ end
33
+
34
+ # The entity type of a MBID didn't match the type of the entity.
35
+ class EntityTypeNotMatchingError < Exception
36
+ end
37
+
38
+ end
39
+ end
40
+
41
+ require 'rbrainz/data/countrynames'
42
+ require 'rbrainz/data/languagenames'
43
+ require 'rbrainz/data/scriptnames'
44
+
45
+ require 'rbrainz/model/artist'
46
+ require 'rbrainz/model/label'
47
+ require 'rbrainz/model/release'
48
+ require 'rbrainz/model/track'
@@ -0,0 +1,23 @@
1
+ # $Id: alias.rb 4 2007-05-21 02:04:26Z phw $
2
+ # Copyright (c) 2007, Philipp Wolfer
3
+ # All rights reserved.
4
+ # See LICENSE for permissions.
5
+
6
+ module MusicBrainz
7
+ module Model
8
+
9
+ # An artist alias.
10
+ #
11
+ # See http://musicbrainz.org/doc/ArtistAlias.
12
+ class Alias
13
+
14
+ attr_accessor :name, :type, :script
15
+
16
+ def to_s
17
+ return name.to_s
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,54 @@
1
+ # $Id: artist.rb 13 2007-05-22 22:59:57Z phw $
2
+ # Copyright (c) 2007, Philipp Wolfer
3
+ # All rights reserved.
4
+ # See LICENSE for permissions.
5
+
6
+ require 'rbrainz/model/entity'
7
+ require 'rbrainz/model/alias'
8
+ require 'rbrainz/model/incomplete_date'
9
+
10
+ module MusicBrainz
11
+ module Model
12
+
13
+ # An artist in the MusicBrainz DB.
14
+ #
15
+ # See http://musicbrainz.org/doc/Artist.
16
+ class Artist < Entity
17
+
18
+ TYPE_PERSON = NS_MMD_1 + 'Person'
19
+ TYPE_GROUP = NS_MMD_1 + 'Group'
20
+
21
+ attr_accessor :name, :sort_name, :disambiguation,
22
+ :type, :aliases, :releases
23
+
24
+ attr_reader :begin_date, :end_date
25
+
26
+ def initialize
27
+ @aliases = Array.new
28
+ @releases = Array.new
29
+ end
30
+
31
+ # Set the begin date of this artist.
32
+ #
33
+ # Should be an IncompleteDate object or
34
+ # a date string, which will get converted
35
+ # into an IncompleteDate.
36
+ def begin_date=(date)
37
+ date = IncompleteDate.new date unless date.is_a? IncompleteDate
38
+ @begin_date = date
39
+ end
40
+
41
+ # Set the end date of this artist.
42
+ #
43
+ # Should be an IncompleteDate object or
44
+ # a date string, which will get converted
45
+ # into an IncompleteDate.
46
+ def end_date=(date)
47
+ date = IncompleteDate.new date unless date.is_a? IncompleteDate
48
+ @end_date = date
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,30 @@
1
+ # $Id: disc.rb 15 2007-05-23 14:31:36Z phw $
2
+ # Copyright (c) 2007, Philipp Wolfer
3
+ # All rights reserved.
4
+ # See LICENSE for permissions.
5
+
6
+ module MusicBrainz
7
+ module Model
8
+
9
+ # Represents an audio CD.
10
+ #
11
+ # A disc has a disc id, which is calculated from the
12
+ # CD's table of contents (TOC). It also can include
13
+ # the numbers of sectors on the CD.
14
+ #
15
+ # The disc id is mainly used to lookup a release in
16
+ # the MusicBrainz database the matches a given disc
17
+ # id. See Webservice::ReleaseFilter for details on
18
+ # this.
19
+ #
20
+ # See http://wiki.musicbrainz.org/DiscID.
21
+ #
22
+ # TODO: Currently the calculation of a disc ID is not supported.
23
+ class Disc
24
+
25
+ attr_accessor :id, :sectors
26
+
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,72 @@
1
+ # $Id: entity.rb 15 2007-05-23 14:31:36Z phw $
2
+ # Copyright (c) 2007, Philipp Wolfer
3
+ # All rights reserved.
4
+ # See LICENSE for permissions.
5
+
6
+ require 'rbrainz/model/mbid'
7
+
8
+ module MusicBrainz
9
+ module Model
10
+
11
+ # Superclass for all entities.
12
+ #
13
+ # TODO: implement relations.
14
+ class Entity
15
+
16
+ attr_reader :id
17
+
18
+ # Set the MBID.
19
+ #
20
+ # +mbid+ should be an instance of +MBID+ or a string
21
+ # representing either a complete MBID URI or just the
22
+ # UUID part of it. If it is a complete URI the entity
23
+ # part of the URI must match the entity type returned
24
+ # by +entity_type+ or an +EntityTypeNotMatchingError+
25
+ # will be raised.
26
+ #
27
+ # Raises: +UnknownEntityError+, +InvalidUUIDError+,
28
+ # +EntityTypeNotMatchingError+
29
+ def id=(mbid)
30
+ # If this already is an instance of MBID store it directly.
31
+ if mbid.is_a? MBID
32
+ @id = mbid
33
+ elsif mbid.nil?
34
+ @id = nil
35
+ else
36
+ # Try to create an MBID from URI
37
+ begin
38
+ @id = MBID.from_uri(mbid)
39
+ rescue InvalidMBIDError => e
40
+ # Try it again and use mbid as the UUID
41
+ @id = MBID.from_uuid(self.entity_type, mbid)
42
+ end
43
+ end
44
+
45
+ # Check if the entity type of @id matches that of the current object.
46
+ unless @id.nil? or @id.entity == self.entity_type
47
+ exception = EntityTypeNotMatchingError.new(@id.entity.to_s)
48
+ @id = nil
49
+ raise exception
50
+ end
51
+ end
52
+
53
+ # Returns the entity type of the entity class.
54
+ #
55
+ # Depending on the class this is <tt>:artist</tt>, <tt>:release</tt>,
56
+ # <tt>:track</tt> or <tt>:label</tt>.
57
+ def self.entity_type
58
+ self.name.sub('MusicBrainz::Model::', '').downcase.to_sym
59
+ end
60
+
61
+ # Returns the entity type of the instance.
62
+ #
63
+ # Depending on the class this is <tt>:artist</tt>, <tt>:release</tt>,
64
+ # <tt>:track</tt> or <tt>:label</tt>.
65
+ def entity_type
66
+ self.class.entity_type
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,76 @@
1
+ # $Id: incomplete_date.rb 17 2007-05-23 16:51:11Z phw $
2
+ # Copyright (c) 2007, Philipp Wolfer
3
+ # All rights reserved.
4
+ # See LICENSE for permissions.
5
+
6
+ require 'date'
7
+
8
+ module MusicBrainz
9
+ module Model
10
+
11
+ # Represents an incomplete date. An incomplete date is
12
+ # a date which can be defined without day or without
13
+ # month and day. It can be written as <em>YYYY</em>,
14
+ # <em>YYYY-MM</em> or <em>YYYY-MM-DD</em>.
15
+ class IncompleteDate
16
+
17
+ attr_reader :year, :month, :day
18
+
19
+ # Include the Comparable module to make incomplete dates
20
+ # comparable and sortable.
21
+ include Comparable
22
+
23
+ # TODO: Validation of the date
24
+ def initialize(date)
25
+ @year = nil
26
+ @month = nil
27
+ @day = nil
28
+ if date = date.to_s and date =~ /^\d{4}(-\d{2}){0,2}$/
29
+ @year = date[0..3].to_i if date.size >= 4
30
+ @month = date[5..6].to_i if date.size >= 7
31
+ @day = date[8..9].to_i if date.size == 10
32
+ elsif not date.empty?
33
+ raise ArgumentError
34
+ end
35
+ end
36
+
37
+ # Returns the incomplete date in its textual form
38
+ # <em>YYYY</em>, <em>YYYY-MM</em> or <em>YYYY-MM-DD</em>.
39
+ #
40
+ # TODO: Allow formatting options similiar to Date.to_s
41
+ def to_s
42
+ date = @year.to_s
43
+ [@month, @day].each {|value|
44
+ date += '-%02d' % value if value
45
+ }
46
+ return date
47
+ end
48
+
49
+ # Compare this incomplete date with another incomplete date.
50
+ # If two incomplete dates are compared of which one date has
51
+ # less information than the other only the information
52
+ # present in both incomplete dates is used for comparison.
53
+ # That means that the dates 1980-08-22, 1980-08 and 1980 are
54
+ # all considered equal if compared to one another since it
55
+ # can't be decided if e.g. the date 1980-08 is earlier or later
56
+ # than 1980-08-22.
57
+ #
58
+ # As a consequence of this a list of +IncompleteDate+ objects
59
+ # won't get sorted in the lexical order of their string
60
+ # representations. If you need a lexical order you must convert
61
+ # these objects to strings before ordering them.
62
+ def <=>(other)
63
+ result = self.year <=> other.year
64
+ if result == 0 and self.month and other.month
65
+ result = self.month <=> other.month
66
+ if result == 0 and self.day and other.day
67
+ result = self.day <=> other.day
68
+ end
69
+ end
70
+ return result
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,55 @@
1
+ # $Id: label.rb 13 2007-05-22 22:59:57Z phw $
2
+ # Copyright (c) 2007, Philipp Wolfer
3
+ # All rights reserved.
4
+ # See LICENSE for permissions.
5
+
6
+ require 'rbrainz/model/entity'
7
+ require 'rbrainz/model/incomplete_date'
8
+
9
+ module MusicBrainz
10
+ module Model
11
+
12
+ # A label in the MusicBrainz DB.
13
+ #
14
+ # See http://musicbrainz.org/doc/Label.
15
+ class Label < Entity
16
+
17
+ TYPE_DISTRIBUTOR = NS_MMD_1 + 'Distributor'
18
+ TYPE_HOLDING = NS_MMD_1 + 'Holding'
19
+ TYPE_ORIGINAL_PRODUCTION = NS_MMD_1 + 'OriginalProduction'
20
+ TYPE_BOOTLEG_PRODUCTION = NS_MMD_1 + 'BootlegProduction'
21
+ TYPE_REISSUE_PRODUCTION = NS_MMD_1 + 'ReissueProduction'
22
+
23
+ attr_accessor :name, :sort_name, :disambiguation,
24
+ :code, :country, :type, :releases
25
+
26
+ attr_reader :founding_date, :dissolving_date
27
+
28
+ def initialize
29
+ @releases = Array.new
30
+ end
31
+
32
+ # Set the founding date of the label.
33
+ #
34
+ # Should be an IncompleteDate object or
35
+ # a date string, which will get converted
36
+ # into an IncompleteDate.
37
+ def founding_date=(date)
38
+ date = IncompleteDate.new date unless date.is_a? IncompleteDate
39
+ @founding_date = date
40
+ end
41
+
42
+ # Set the dissolving date of the label.
43
+ #
44
+ # Should be an IncompleteDate object or
45
+ # a date string, which will get converted
46
+ # into an IncompleteDate.
47
+ def dissolving_date=(date)
48
+ date = IncompleteDate.new date unless date.is_a? IncompleteDate
49
+ @dissolving_date = date
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,82 @@
1
+ # $Id: mbid.rb 17 2007-05-23 16:51:11Z phw $
2
+ # Copyright (c) 2007, Philipp Wolfer
3
+ # All rights reserved.
4
+ # See LICENSE for permissions.
5
+
6
+ require 'rbrainz/model'
7
+
8
+ module MusicBrainz
9
+ module Model
10
+
11
+ # Represents a MusicBrainz identifier.
12
+ #
13
+ # A MusicBrainz identifier is an URI identifying a resource like an artist or a track.
14
+ # It consists of an URI prefix, the entity type it refers to and an UUID that
15
+ # identifies the referenced entity.
16
+ #
17
+ # See http://musicbrainz.org/doc/MusicBrainzIdentifier.
18
+ #
19
+ # Example: http://musicbrainz.org/artist/6a2ca1ac-408d-49b0-a7f6-cd608f2f684f.
20
+ class MBID
21
+
22
+ attr_reader :entity, :uuid
23
+
24
+ ENTITY_URI = 'http://musicbrainz.org/%s/%s'
25
+ ENTITY_URI_REGEXP = /^http:\/\/musicbrainz.org\/(artist|release|track|label)\/([a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12})\/?$/
26
+
27
+ # We make new private. Use from_uri or from_uuid instead.
28
+ private_class_method :new
29
+
30
+ # Creates a new MBID from a MBID URI, e.g.
31
+ # http://musicbrainz.org/artist/6a2ca1ac-408d-49b0-a7f6-cd608f2f684f
32
+ def self.from_uri(uri)
33
+ if match = ENTITY_URI_REGEXP.match(uri)
34
+ entity = match[1]
35
+ uuid = match[2]
36
+ else
37
+ raise InvalidMBIDError.new(uri.inspect)
38
+ end
39
+ from_uuid(entity, uuid)
40
+ end
41
+
42
+ # Create a new MBID from the entity type and the UUID.
43
+ #
44
+ # The entity type must be <tt>:artist</tt>, <tt>:release</tt>,
45
+ # <tt>:track</tt> or <tt>:label</tt>. The UUID is the last
46
+ # part of the URI, e.g. <tt>6a2ca1ac-408d-49b0-a7f6-cd608f2f684f</tt>.
47
+ #
48
+ # Raises: +UnknownEntityError+, +InvalidUUIDError+
49
+ def self.from_uuid(entity, uuid)
50
+ if entity.nil? or entity == '' or
51
+ not [:artist, :release, :track, :label].include? entity.to_sym
52
+ raise UnknownEntityError.new(entity.to_s)
53
+ end
54
+ unless uuid.is_a? String and uuid =~ UUID_REGEXP
55
+ raise InvalidUUIDError.new(uuid.inspect)
56
+ end
57
+ new(entity.to_sym, uuid)
58
+ end
59
+
60
+ # Initialize the UUID given the entity type and an UUID.
61
+ def initialize(entity, uuid) # :notnew:
62
+ @entity = entity
63
+ @uuid = uuid
64
+ end
65
+
66
+ # Returns the string representation of the MBID (that is the complete URI).
67
+ def to_s
68
+ ENTITY_URI % [entity.to_s, uuid]
69
+ end
70
+
71
+ # Compares this MBID with another one.
72
+ #
73
+ # Two MBIDs are considered equal if both their entity
74
+ # type and their UUID are equal.
75
+ def ==(other)
76
+ self.entity == other.entity and self.uuid == other.uuid
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+ end