w3c_api 0.1.0 → 0.1.1

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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +1 -1
  3. data/README.adoc +845 -436
  4. data/lib/w3c_api/cli.rb +20 -20
  5. data/lib/w3c_api/client.rb +66 -195
  6. data/lib/w3c_api/commands/affiliation.rb +33 -33
  7. data/lib/w3c_api/commands/ecosystem.rb +47 -47
  8. data/lib/w3c_api/commands/group.rb +68 -68
  9. data/lib/w3c_api/commands/output_formatter.rb +11 -11
  10. data/lib/w3c_api/commands/participation.rb +20 -22
  11. data/lib/w3c_api/commands/series.rb +26 -26
  12. data/lib/w3c_api/commands/specification.rb +77 -52
  13. data/lib/w3c_api/commands/translation.rb +18 -18
  14. data/lib/w3c_api/commands/user.rb +60 -60
  15. data/lib/w3c_api/hal.rb +164 -0
  16. data/lib/w3c_api/models/account.rb +44 -0
  17. data/lib/w3c_api/models/affiliation.rb +54 -65
  18. data/lib/w3c_api/models/affiliation_index.rb +11 -0
  19. data/lib/w3c_api/models/call_for_translation.rb +15 -39
  20. data/lib/w3c_api/models/chair_index.rb +11 -0
  21. data/lib/w3c_api/models/charter.rb +48 -89
  22. data/lib/w3c_api/models/charter_index.rb +11 -0
  23. data/lib/w3c_api/models/connected_account.rb +21 -30
  24. data/lib/w3c_api/models/ecosystem.rb +20 -42
  25. data/lib/w3c_api/models/{ecosystems.rb → ecosystem_index.rb} +4 -10
  26. data/lib/w3c_api/models/evangelist_index.rb +11 -0
  27. data/lib/w3c_api/models/extension.rb +5 -7
  28. data/lib/w3c_api/models/group.rb +63 -142
  29. data/lib/w3c_api/models/group_index.rb +12 -0
  30. data/lib/w3c_api/models/join_emails.rb +5 -7
  31. data/lib/w3c_api/models/participant_index.rb +11 -0
  32. data/lib/w3c_api/models/participation.rb +31 -90
  33. data/lib/w3c_api/models/participation_index.rb +11 -0
  34. data/lib/w3c_api/models/photo.rb +26 -0
  35. data/lib/w3c_api/models/serie.rb +21 -51
  36. data/lib/w3c_api/models/{series.rb → serie_index.rb} +22 -13
  37. data/lib/w3c_api/models/spec_version.rb +69 -83
  38. data/lib/w3c_api/models/spec_version_index.rb +13 -0
  39. data/lib/w3c_api/models/spec_version_ref.rb +11 -13
  40. data/lib/w3c_api/models/specification.rb +54 -66
  41. data/lib/w3c_api/models/specification_index.rb +10 -0
  42. data/lib/w3c_api/models/team_contact_index.rb +11 -0
  43. data/lib/w3c_api/models/testimonial.rb +17 -0
  44. data/lib/w3c_api/models/translation.rb +33 -72
  45. data/lib/w3c_api/models/{translations.rb → translation_index.rb} +4 -12
  46. data/lib/w3c_api/models/user.rb +95 -165
  47. data/lib/w3c_api/models/user_index.rb +11 -0
  48. data/lib/w3c_api/models.rb +35 -12
  49. data/lib/w3c_api/version.rb +1 -1
  50. data/lib/w3c_api.rb +3 -2
  51. metadata +35 -19
  52. data/lib/w3c_api/models/affiliations.rb +0 -33
  53. data/lib/w3c_api/models/base.rb +0 -39
  54. data/lib/w3c_api/models/call_for_translation_ref.rb +0 -15
  55. data/lib/w3c_api/models/charters.rb +0 -17
  56. data/lib/w3c_api/models/collection_base.rb +0 -79
  57. data/lib/w3c_api/models/delegate_enumerable.rb +0 -54
  58. data/lib/w3c_api/models/groups.rb +0 -38
  59. data/lib/w3c_api/models/link.rb +0 -17
  60. data/lib/w3c_api/models/participations.rb +0 -17
  61. data/lib/w3c_api/models/series_collection.rb +0 -17
  62. data/lib/w3c_api/models/spec_versions.rb +0 -17
  63. data/lib/w3c_api/models/specifications.rb +0 -17
  64. data/lib/w3c_api/models/users.rb +0 -44
@@ -0,0 +1,164 @@
1
+ require 'singleton'
2
+ require_relative 'models'
3
+
4
+ module W3cApi
5
+ class Hal
6
+ include Singleton
7
+
8
+ def initialize
9
+ setup
10
+ end
11
+
12
+ def client
13
+ @client ||= Lutaml::Hal::Client.new(api_url: 'https://api.w3.org/')
14
+ end
15
+
16
+ def register
17
+ return @register if @register
18
+
19
+ @register = Lutaml::Hal::ModelRegister.new(name: :w3c_api, client: client)
20
+ Lutaml::Hal::GlobalRegister.instance.register(:w3c_api, @register)
21
+ @register
22
+ end
23
+
24
+ def setup
25
+ register.add_endpoint(id: :affiliation_index, type: :index, url: '/affiliations', model: Models::AffiliationIndex)
26
+ register.add_endpoint(id: :affiliation_resource, type: :resource, url: '/affiliations/{id}',
27
+ model: Models::Affiliation)
28
+ register.add_endpoint(id: :affiliation_participants_index, type: :index, url: '/affiliations/{id}/participants',
29
+ model: Models::ParticipantIndex)
30
+ register.add_endpoint(id: :affiliation_participations_index, type: :index, url: '/affiliations/{id}/participations',
31
+ model: Models::ParticipationIndex)
32
+
33
+ # register.add_endpoint(id: :charter_resource, type: :resource, url: '/charters/{id}', model: Models::Charter)
34
+
35
+ register.add_endpoint(id: :ecosystem_index, type: :index, url: '/ecosystems', model: Models::EcosystemIndex)
36
+ register.add_endpoint(id: :ecosystem_resource, type: :resource, url: '/ecosystems/{id}', model: Models::Ecosystem)
37
+ register.add_endpoint(id: :ecosystem_evangelists_index, type: :index, url: '/ecosystems/{shortname}/evangelists',
38
+ model: Models::EvangelistIndex)
39
+ register.add_endpoint(id: :ecosystem_groups_index, type: :index, url: '/ecosystems/{shortname}/groups',
40
+ model: Models::GroupIndex)
41
+ register.add_endpoint(id: :ecosystem_member_organizations_index, type: :index, url: '/ecosystems/{shortname}/member-organizations',
42
+ model: Models::AffiliationIndex)
43
+
44
+ register.add_endpoint(id: :group_index, type: :index, url: '/groups', model: Models::GroupIndex)
45
+ register.add_endpoint(id: :group_resource, type: :resource, url: '/groups/{id}', model: Models::Group)
46
+ register.add_endpoint(id: :group_specifications_index, type: :index, url: '/groups/{id}/specifications',
47
+ model: Models::SpecificationIndex)
48
+ register.add_endpoint(id: :group_charters_index, type: :index, url: '/groups/{id}/charters',
49
+ model: Models::CharterIndex)
50
+ register.add_endpoint(id: :group_users_index, type: :index, url: '/groups/{id}/users',
51
+ model: Models::UserIndex)
52
+ register.add_endpoint(id: :group_chairs_index, type: :index, url: '/groups/{id}/chairs',
53
+ model: Models::ChairIndex)
54
+ register.add_endpoint(id: :group_team_contacts_index, type: :index, url: '/groups/{id}/teamcontacts',
55
+ model: Models::TeamContactIndex)
56
+ register.add_endpoint(id: :group_participations_index, type: :index, url: '/groups/{id}/participations',
57
+ model: Models::ParticipationIndex)
58
+
59
+ # register.add_endpoint(id: :participation_index, type: :index, url: '/participations', model: Models::ParticipationIndex)
60
+ register.add_endpoint(id: :participation_resource, type: :resource, url: '/participations/{id}',
61
+ model: Models::Participation)
62
+ register.add_endpoint(id: :participation_participants_index, type: :index, url: '/participations/{id}/participants',
63
+ model: Models::ParticipantIndex)
64
+
65
+ register.add_endpoint(id: :serie_index, type: :index, url: '/specification-series', model: Models::SerieIndex)
66
+ register.add_endpoint(id: :serie_resource, type: :resource, url: '/specification-series/{shortname}',
67
+ model: Models::Serie)
68
+
69
+ register.add_endpoint(id: :serie_specification_resource, type: :index,
70
+ url: '/specification-series/{shortname}/specifications', model: Models::SpecificationIndex)
71
+
72
+ register.add_endpoint(id: :specification_index, type: :index, url: '/specifications',
73
+ model: Models::SpecificationIndex)
74
+ register.add_endpoint(id: :specification_resource, type: :resource, url: '/specifications/{shortname}',
75
+ model: Models::Specification)
76
+ register.add_endpoint(id: :specification_resource_version_index, type: :index, url: '/specifications/{shortname}/versions',
77
+ model: Models::SpecVersionIndex)
78
+
79
+ register.add_endpoint(
80
+ id: :specification_resource_version_resource,
81
+ type: :resource,
82
+ url: '/specifications/{shortname}/versions/{version}',
83
+ model: Models::SpecVersion
84
+ )
85
+ register.add_endpoint(
86
+ id: :specification_version_predecessors_index,
87
+ type: :index,
88
+ url: '/specifications/{shortname}/versions/{version}/predecessors',
89
+ model: Models::SpecVersionIndex
90
+ )
91
+ register.add_endpoint(
92
+ id: :specification_version_successors_index,
93
+ type: :index,
94
+ url: '/specifications/{shortname}/versions/{version}/successors',
95
+ model: Models::SpecVersionIndex
96
+ )
97
+ register.add_endpoint(
98
+ id: :specification_by_status_index,
99
+ type: :index,
100
+ url: '/specifications-by-status/{status}',
101
+ model: Models::SpecificationIndex
102
+ )
103
+ register.add_endpoint(
104
+ id: :specification_supersedes_index,
105
+ type: :index,
106
+ url: '/specifications/{shortname}/supersedes',
107
+ model: Models::SpecificationIndex
108
+ )
109
+ register.add_endpoint(
110
+ id: :specification_superseded_by_index,
111
+ type: :index,
112
+ url: '/specifications/{shortname}/superseded',
113
+ model: Models::SpecificationIndex
114
+ )
115
+ register.add_endpoint(
116
+ id: :specification_version_editors_index,
117
+ type: :index,
118
+ url: '/specifications/{shortname}/version/{version}/editors',
119
+ model: Models::UserIndex
120
+ )
121
+ register.add_endpoint(
122
+ id: :specification_version_deliverers_index,
123
+ type: :index,
124
+ url: '/specifications/{shortname}/version/{version}/deliverers',
125
+ model: Models::UserIndex
126
+ )
127
+
128
+ # TODO: Why is this endpoint needed? There already is /specifications/{shortname}...
129
+ # register.add_endpoint(
130
+ # id: :specification_by_shortname_index,
131
+ # type: :index,
132
+ # url: '/specifications-by-shortname/{shortname}',
133
+ # model: Models::SpecificationIndex
134
+ # )
135
+
136
+ register.add_endpoint(id: :translation_index, type: :index, url: '/translations', model: Models::TranslationIndex)
137
+ register.add_endpoint(id: :translation_resource, type: :resource, url: '/translations/{id}',
138
+ model: Models::Translation)
139
+
140
+ # NOTE: This endpoint doesn't exist, just here for reference.
141
+ # register.add_endpoint(id: :user_index, type: :index, url: '/users', model: Models::UserIndex)
142
+
143
+ register.add_endpoint(id: :user_groups_index, type: :index, url: '/users/{hash}/groups',
144
+ model: Models::GroupIndex)
145
+
146
+ register.add_endpoint(id: :user_resource, type: :resource, url: '/users/{hash}', model: Models::User)
147
+
148
+ register.add_endpoint(id: :user_affiliations_index, type: :index, url: '/users/{hash}/affiliations',
149
+ model: Models::AffiliationIndex)
150
+
151
+ register.add_endpoint(id: :user_participations_index, type: :index, url: '/users/{hash}/participations',
152
+ model: Models::ParticipationIndex)
153
+
154
+ register.add_endpoint(id: :user_chair_of_groups_index, type: :index, url: '/users/{hash}/chair-of-groups',
155
+ model: Models::GroupIndex)
156
+
157
+ register.add_endpoint(id: :user_team_contact_of_groups_index, type: :index, url: '/users/{hash}/team-contact-of-groups',
158
+ model: Models::GroupIndex)
159
+
160
+ register.add_endpoint(id: :user_specifications_index, type: :index, url: '/users/{hash}/specifications',
161
+ model: Models::SpecificationIndex)
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,44 @@
1
+ require 'lutaml/hal'
2
+ # {
3
+ # "created": "2021-03-12T22:06:06+00:00",
4
+ # "service": "github",
5
+ # "identifier": "57469",
6
+ # "nickname": "jenstrickland",
7
+ # "profile-picture": "https://avatars.githubusercontent.com/u/57469?v=4",
8
+ # "href": "https://github.com/jenstrickland",
9
+ # "_links": {
10
+ # "user": {
11
+ # "href": "https://api.w3.org/users/f1ovb5rydm8s0go04oco0cgk0sow44w"
12
+ # }
13
+ # }
14
+ # }
15
+
16
+ module W3cApi
17
+ module Models
18
+ # User model representing a W3C user/participant
19
+ class Account < Lutaml::Hal::Resource
20
+ attribute :created, :date_time
21
+ attribute :updated, :date_time
22
+ attribute :identifier, :string
23
+ attribute :nickname, :string
24
+ attribute :service, :string
25
+ attribute :profile_picture, :string
26
+ attribute :href, :string
27
+
28
+ hal_link :user, key: 'user', realize_class: 'User'
29
+
30
+ key_value do
31
+ %i[
32
+ created
33
+ updated
34
+ identifier
35
+ nickname
36
+ service
37
+ profile_picture
38
+ ].each do |key|
39
+ map key.to_s.tr('_', '-'), to: key
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,27 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'base'
4
- require_relative 'link'
5
-
6
- # Example affiliation response:
3
+ # https://api.w3.org/affiliations/35662
7
4
  # {
8
- # "id"=>48830,
9
- # "name"=>"Postmedia",
10
- # "discr"=>"organization",
11
- # "is-member"=>false,
12
- # "is-member-association"=>false,
13
- # "is-partner-member"=>false,
14
- # "_links"=>{
15
- # "self"=>{
16
- # "href"=>"https://api.w3.org/affiliations/48830"
17
- # },
18
- # "participants"=>{
19
- # "href"=>"https://api.w3.org/affiliations/48830/participants"
5
+ # "id": 35662,
6
+ # "name": "Google LLC",
7
+ # "discr": "organization",
8
+ # "testimonials": {
9
+ # "en": "Google's mission is to organize the world’s information and make it universally accessible and useful."
20
10
  # },
21
- # "participations"=>{
22
- # "href"=>"https://api.w3.org/affiliations/48830/participations"
11
+ # "is-member": true,
12
+ # "is-member-association": false,
13
+ # "is-partner-member": false,
14
+ # "_links": {
15
+ # "homepage": {
16
+ # "href": "http://www.google.com/"
17
+ # },
18
+ # "self": {
19
+ # "href": "https://api.w3.org/affiliations/35662"
20
+ # },
21
+ # "participants": {
22
+ # "href": "https://api.w3.org/affiliations/35662/participants"
23
+ # },
24
+ # "participations": {
25
+ # "href": "https://api.w3.org/affiliations/35662/participations"
26
+ # },
27
+ # "logo": {
28
+ # "href": "https://www.w3.org/thumbnails/250/logos/organizations/35662.png?x-version=1"
29
+ # }
23
30
  # }
24
- # }
25
31
  # }
26
32
 
27
33
  # Fetch index response:
@@ -30,57 +36,40 @@ require_relative 'link'
30
36
  # "title"=>"Framkom (Forskningsaktiebolaget Medie-och Kommunikationsteknik)"
31
37
  # },
32
38
 
39
+ require_relative 'testimonial'
33
40
 
34
41
  module W3cApi
35
- module Models
36
- class AffiliationLinks < Lutaml::Model::Serializable
37
- attribute :self, Link
38
- attribute :participants, Link
39
- attribute :participations, Link
40
- end
41
-
42
- class Affiliation < Base
43
- attribute :id, :integer
44
- attribute :name, :string
45
- attribute :href, :string
46
- attribute :title, :string
47
- attribute :descr, :string
48
- attribute :is_member, :boolean
49
- attribute :is_member_association, :boolean
50
- attribute :is_partner_member, :boolean
51
- attribute :_links, AffiliationLinks
52
-
53
- # Get participants of this affiliation
54
- def participants(client = nil)
55
- return nil unless client && _links&.participants
56
-
57
- client.affiliation_participants(id)
58
- end
59
-
60
- # Get participations of this affiliation
61
- def participations(client = nil)
62
- return nil unless client && _links&.participations
63
-
64
- client.affiliation_participations(id)
65
- end
42
+ module Models
43
+ class Affiliation < Lutaml::Hal::Resource
44
+ attribute :id, :integer
45
+ attribute :name, :string
46
+ attribute :href, :string
47
+ attribute :title, :string
48
+ attribute :discr, :string
49
+ attribute :testimonials, Testimonial
50
+ attribute :is_member, :boolean
51
+ attribute :is_member_association, :boolean
52
+ attribute :is_partner_member, :boolean
66
53
 
67
- def self.from_response(response)
68
- transformed_response = transform_keys(response)
54
+ hal_link :self, key: 'self', realize_class: 'Affiliation'
55
+ hal_link :homepage, key: 'homepage', realize_class: 'String'
56
+ hal_link :participants, key: 'participants', realize_class: 'Participant'
57
+ hal_link :participations, key: 'participations', realize_class: 'Participation'
58
+ hal_link :logo, key: 'logo', realize_class: 'String'
69
59
 
70
- affiliation = new
71
- transformed_response.each do |key, value|
72
- case key
73
- when :_links
74
- links = value.each_with_object({}) do |(link_name, link_data), acc|
75
- acc[link_name] = Link.new(href: link_data[:href], title: link_data[:title])
76
- end
77
- affiliation._links = AffiliationLinks.new(links)
78
- else
79
- affiliation.send("#{key}=", value) if affiliation.respond_to?("#{key}=")
80
- end
81
- end
82
- affiliation
60
+ key_value do
61
+ %i[
62
+ id
63
+ name
64
+ discr
65
+ testimonials
66
+ is_member
67
+ is_member_association
68
+ is_partner_member
69
+ ].each do |key|
70
+ map key.to_s.tr('_', '-'), to: key
83
71
  end
84
72
  end
85
73
  end
74
+ end
86
75
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'affiliation'
4
+
5
+ module W3cApi
6
+ module Models
7
+ class AffiliationIndex < Lutaml::Hal::Page
8
+ hal_link :affiliations, key: 'affiliations', realize_class: 'Affiliation', collection: true
9
+ end
10
+ end
11
+ end
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'base'
4
- require_relative 'link'
5
- require_relative 'spec_version_ref'
6
-
7
3
  # {
8
4
  # "uri": "https://www.w3.org/WAI/videos/standards-and-benefits/"
9
5
  # "title": "Video Introduction to Web Accessibility and W3C Standards"
@@ -18,42 +14,22 @@ require_relative 'spec_version_ref'
18
14
  # }
19
15
 
20
16
  module W3cApi
21
- module Models
22
- class CallForTranslationLinks < Lutaml::Model::Serializable
23
- attribute :self, Link
24
- attribute :translations, Link
25
- end
26
-
27
- class CallForTranslation < Base
28
- attribute :uri, :string
29
- attribute :title, :string
30
- attribute :spec_version, SpecVersionRef
31
- attribute :_links, CallForTranslationLinks
32
-
33
- # Get translations for this call for translation
34
- def translations(client = nil)
35
- return nil unless client && _links&.translations
36
-
37
- client.call_for_translation_translations(uri)
38
- end
39
-
40
- def self.from_response(response)
41
- transformed_response = transform_keys(response)
42
-
43
- cft = new
44
- transformed_response.each do |key, value|
45
- case key
46
- when :_links
47
- links = value.each_with_object({}) do |(link_name, link_data), acc|
48
- acc[link_name] = Link.new(href: link_data[:href], title: link_data[:title])
49
- end
50
- cft._links = CallForTranslationLinks.new(links)
51
- else
52
- cft.send("#{key}=", value) if cft.respond_to?("#{key}=")
53
- end
54
- end
55
- cft
17
+ module Models
18
+ class CallForTranslation < Lutaml::Hal::Resource
19
+ attribute :uri, :string
20
+ attribute :title, :string
21
+
22
+ hal_link :self, key: 'self', realize_class: 'CallForTranslation'
23
+ hal_link :translations, key: 'translations', realize_class: 'TranslationIndex'
24
+
25
+ key_value do
26
+ %i[
27
+ uri
28
+ title
29
+ ].each do |key|
30
+ map key.to_s.tr('_', '-'), to: key
56
31
  end
57
32
  end
58
33
  end
34
+ end
59
35
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'user'
4
+
5
+ module W3cApi
6
+ module Models
7
+ class ChairIndex < Lutaml::Hal::Page
8
+ hal_link :chairs, key: 'chairs', realize_class: 'User', collection: true
9
+ end
10
+ end
11
+ end
@@ -1,110 +1,69 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'base'
4
3
  require_relative 'extension'
5
- require_relative 'link'
6
4
 
7
- # Example charter response format - specific fields may vary by group:
5
+ # https://api.w3.org/groups/109735/charters/361
8
6
  # {
9
- # "end": "2025-10-31"
10
- # "title": "Accessibility Guidelines Working Group Charter"
11
- # "start": "1997-10-06"
12
- # "initial_end": "1999-10-06"
13
- # "uri": "https://www.w3.org/2022/05/accessibility-guidelines-wg-charter.html"
14
- # "cfp_uri": "https://lists.w3.org/Archives/Member/w3c-ac-members/..."
15
- # "extensions": [...]
16
- # "required_new_commitments": false
17
- # "patent_policy": "pre-2020"
7
+ # "end": "2020-04-30",
8
+ # "doc-licenses": [],
9
+ # "start": "2018-09-24",
10
+ # "initial-end": "2020-03-01",
11
+ # "uri": "https://www.w3.org/2018/09/immersive-web-wg-charter.html",
12
+ # "cfp-uri": "https://lists.w3.org/Archives/Member/w3c-ac-members/2018JulSep/0053.html",
13
+ # "extensions": [
14
+ # {
15
+ # "end": "2020-04-30",
16
+ # "announcement_uri": "https://lists.w3.org/Archives/Member/w3c-ac-members/2020JanMar/0028.html"
17
+ # }
18
+ # ],
19
+ # "required-new-commitments": true,
20
+ # "patent-policy": "https://www.w3.org/Consortium/Patent-Policy-20170801/",
18
21
  # "_links": {
19
22
  # "self": {
20
- # "href": "https://api.w3.org/groups/wg/ag/charters/492"
23
+ # "href": "https://api.w3.org/groups/wg/immersive-web/charters/361"
21
24
  # },
22
25
  # "group": {
23
- # "href": "https://api.w3.org/groups/wg/ag"
26
+ # "href": "https://api.w3.org/groups/wg/immersive-web",
27
+ # "title": "Immersive Web Working Group"
28
+ # },
29
+ # "next-charter": {
30
+ # "href": "https://api.w3.org/groups/wg/immersive-web/charters/405"
24
31
  # }
25
32
  # }
26
33
  # }
27
34
 
28
35
  module W3cApi
29
- module Models
30
- class CharterLinks < Lutaml::Model::Serializable
31
- attribute :self, Link
32
- attribute :group, Link
33
- end
34
-
35
- class Charter < Base
36
- attribute :end, :string # Date-time format
37
- attribute :href, :string
38
- attribute :title, :string
39
- attribute :start, :string # Date-time format
40
- attribute :initial_end, :string # Date-time format
41
- attribute :uri, :string, pattern: %r{https?://www\.w3\.org.*}
42
- attribute :cfp_uri, :string, pattern: %r{https://lists\.w3\.org/Archives/Member/w3c-ac-members/.*}
43
- attribute :extensions, Extension, collection: true
44
- attribute :required_new_commitments, :boolean
45
- attribute :patent_policy, :string
46
- attribute :_links, CharterLinks
47
-
48
- # Return the group this charter belongs to
49
- def group(client = nil)
50
- return nil unless client && _links&.group
51
-
52
- group_href = _links.group.href
53
- group_id = group_href.split('/').last
54
-
55
- client.group(group_id)
56
- end
57
-
58
- # Parse date strings to Date objects
59
- def end_date
60
- Date.parse(self.end) if self.end
61
- rescue Date::Error
62
- nil
63
- end
64
-
65
- def start_date
66
- Date.parse(start) if start
67
- rescue Date::Error
68
- nil
69
- end
70
-
71
- def initial_end_date
72
- Date.parse(initial_end) if initial_end
73
- rescue Date::Error
74
- nil
75
- end
76
-
77
- # Check if this charter is active
78
- def active?
79
- start_date &&
80
- (end_date.nil? || end_date >= Date.today) &&
81
- start_date <= Date.today
82
- rescue Date::Error
83
- false
84
- end
85
-
86
- # Check if this charter has been extended
87
- def extended?
88
- !extensions.nil? && !extensions.empty?
89
- end
36
+ module Models
37
+ class Charter < Lutaml::Hal::Resource
38
+ attribute :end, :date_time
39
+ attribute :doc_licenses, :string, collection: true
40
+ attribute :start, :date_time
41
+ attribute :initial_end, :date_time
42
+ attribute :uri, :string
43
+ attribute :cfp_uri, :string
44
+ attribute :extensions, Extension, collection: true
45
+ attribute :required_new_commitments, :boolean
46
+ attribute :patent_policy, :string
90
47
 
91
- def self.from_response(response)
92
- transformed_response = transform_keys(response)
48
+ hal_link :self, key: 'self', realize_class: 'Charter'
49
+ hal_link :group, key: 'group', realize_class: 'Group'
50
+ hal_link :next_charter, key: 'next-charter', realize_class: 'Charter'
93
51
 
94
- charter = new
95
- transformed_response.each do |key, value|
96
- case key
97
- when :_links
98
- links = value.each_with_object({}) do |(link_name, link_data), acc|
99
- acc[link_name] = Link.new(href: link_data[:href], title: link_data[:title])
100
- end
101
- charter._links = CharterLinks.new(links)
102
- else
103
- charter.send("#{key}=", value) if charter.respond_to?("#{key}=")
104
- end
52
+ key_value do
53
+ %i[
105
54
  end
106
- charter
55
+ doc_licenses
56
+ start
57
+ initial_end
58
+ uri
59
+ cfp_uri
60
+ extensions
61
+ required_new_commitments
62
+ patent_policy
63
+ ].each do |key|
64
+ map key.to_s.tr('_', '-'), to: key
107
65
  end
108
66
  end
109
67
  end
68
+ end
110
69
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'charter'
4
+
5
+ module W3cApi
6
+ module Models
7
+ class CharterIndex < Lutaml::Hal::Page
8
+ hal_link :charters, key: 'charters', realize_class: 'Charter', collection: true
9
+ end
10
+ end
11
+ end