cff 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,16 +12,21 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- #
15
+ ##
16
16
  module CFF
17
17
 
18
- # :stopdoc:
18
+ # ModelPart is the superclass of anything that makes up part of the CFF Model.
19
+ # This includes Model, Person, Entity and Reference.
20
+ #
21
+ # ModelPart does not provide any methods or fields for the public API.
19
22
  class ModelPart
23
+
24
+ # :stopdoc:
20
25
  include Util
21
26
 
22
27
  attr_reader :fields
23
28
 
24
- def method_missing(name, *args) # :nodoc:
29
+ def method_missing(name, *args)
25
30
  n = method_to_field(name.id2name)
26
31
  super unless self.class::ALLOWED_FIELDS.include?(n.chomp('='))
27
32
 
@@ -32,6 +37,11 @@ module CFF
32
37
  end
33
38
  end
34
39
 
40
+ def respond_to_missing?(name, *)
41
+ n = method_to_field(name.id2name)
42
+ self.class::ALLOWED_FIELDS.include?(n.chomp('=')) || super
43
+ end
44
+
45
+ # :startdoc:
35
46
  end
36
- # :startdoc:
37
47
  end
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- #
15
+ ##
16
16
  module CFF
17
17
 
18
18
  # A Person represents a person in a CITATION.cff file. A Person might have a
@@ -20,21 +20,9 @@ module CFF
20
20
  class Person < ModelPart
21
21
 
22
22
  ALLOWED_FIELDS = [
23
- 'address',
24
- 'affiliation',
25
- 'city',
26
- 'country',
27
- 'email',
28
- 'family-names',
29
- 'fax',
30
- 'given-names',
31
- 'name-particle',
32
- 'name-suffix',
33
- 'orcid',
34
- 'post-code',
35
- 'region',
36
- 'tel',
37
- 'website'
23
+ 'address', 'affiliation', 'city', 'country', 'email', 'family-names',
24
+ 'fax', 'given-names', 'name-particle', 'name-suffix', 'orcid',
25
+ 'post-code', 'region', 'tel', 'website'
38
26
  ].freeze # :nodoc:
39
27
 
40
28
  # :call-seq:
@@ -42,7 +30,7 @@ module CFF
42
30
  #
43
31
  # Create a new Person with the supplied given and family names.
44
32
  def initialize(param, *more)
45
- if Hash === param
33
+ if param.is_a?(Hash)
46
34
  @fields = param
47
35
  else
48
36
  @fields = Hash.new('')
@@ -50,6 +38,5 @@ module CFF
50
38
  @fields['given-names'] = param
51
39
  end
52
40
  end
53
-
54
41
  end
55
42
  end
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- #
15
+ ##
16
16
  module CFF
17
17
 
18
18
  # Reference provides a reference pertaining to the software version or the
@@ -22,262 +22,65 @@ module CFF
22
22
  class Reference < ModelPart
23
23
 
24
24
  ALLOWED_FIELDS = [
25
- 'abbreviation',
26
- 'abstract',
27
- 'collection-doi',
28
- 'collection-title',
29
- 'collection-type',
30
- 'commit',
31
- 'conference',
32
- 'copyright',
33
- 'data-type',
34
- 'database',
35
- 'database-provider',
36
- 'date-accessed',
37
- 'date-downloaded',
38
- 'date-published',
39
- 'date-released',
40
- 'department',
41
- 'doi',
42
- 'edition',
43
- 'end',
44
- 'entry',
45
- 'filename',
46
- 'institution',
47
- 'isbn',
48
- 'issn',
49
- 'issue',
50
- 'issue-date',
51
- 'issue-title',
52
- 'journal',
53
- 'keywords',
54
- 'license',
55
- 'license-url',
56
- 'loc-end',
57
- 'loc-start',
58
- 'location',
59
- 'medium',
60
- 'month',
61
- 'nihmsid',
62
- 'notes',
63
- 'number',
64
- 'number-volumes',
65
- 'pages',
66
- 'patent-states',
67
- 'pmcid',
68
- 'publisher',
69
- 'repository',
70
- 'repository-code',
71
- 'repository-artifact',
72
- 'scope',
73
- 'section',
74
- 'start',
75
- 'status',
76
- 'thesis-type',
77
- 'title',
78
- 'type',
79
- 'url',
80
- 'version',
81
- 'volume',
82
- 'volume-title',
83
- 'year',
25
+ 'abbreviation', 'abstract', 'authors', 'collection-doi',
26
+ 'collection-title', 'collection-type', 'commit', 'conference', 'contact',
27
+ 'copyright', 'data-type', 'database', 'database-provider',
28
+ 'date-accessed', 'date-downloaded', 'date-published', 'date-released',
29
+ 'department', 'doi', 'edition', 'editors', 'editors-series', 'end',
30
+ 'entry', 'filename', 'institution', 'isbn', 'issn', 'issue', 'issue-date',
31
+ 'issue-title', 'journal', 'keywords', 'license', 'license-url', 'loc-end',
32
+ 'loc-start', 'location', 'medium', 'month', 'nihmsid', 'notes', 'number',
33
+ 'number-volumes', 'pages', 'patent-states', 'pmcid', 'publisher',
34
+ 'recipients', 'repository', 'repository-code', 'repository-artifact',
35
+ 'scope', 'section', 'senders', 'start', 'status', 'thesis-type', 'title',
36
+ 'translators', 'type', 'url', 'version', 'volume', 'volume-title', 'year',
84
37
  'year-original'
85
38
  ].freeze # :nodoc:
86
39
 
87
40
  # The [defined set of reference types](https://citation-file-format.github.io/1.0.3/specifications/#/reference-types).
88
41
  REFERENCE_TYPES = [
89
- 'art',
90
- 'article',
91
- 'audiovisual',
92
- 'bill',
93
- 'blog',
94
- 'book',
95
- 'catalogue',
96
- 'conference',
97
- 'conference-paper',
98
- 'data',
99
- 'database',
100
- 'dictionary',
101
- 'edited-work',
102
- 'encyclopedia',
103
- 'film-broadcast',
104
- 'generic',
105
- 'government-document',
106
- 'grant',
107
- 'hearing',
108
- 'historical-work',
109
- 'legal-case',
110
- 'legal-rule',
111
- 'magazine-article',
112
- 'manual',
113
- 'map',
114
- 'multimedia',
115
- 'music',
116
- 'newspaper-article',
117
- 'pamphlet',
118
- 'patent',
119
- 'personal-communication',
120
- 'proceedings',
121
- 'report',
122
- 'serial',
123
- 'slides',
124
- 'software',
125
- 'software-code',
126
- 'software-container',
127
- 'software-executable',
128
- 'software-virtual-machine',
129
- 'sound-recording',
130
- 'standard',
131
- 'statute',
132
- 'thesis',
133
- 'unpublished',
134
- 'video',
135
- 'website'
42
+ 'art', 'article', 'audiovisual', 'bill', 'blog', 'book', 'catalogue',
43
+ 'conference', 'conference-paper', 'data', 'database', 'dictionary',
44
+ 'edited-work', 'encyclopedia', 'film-broadcast', 'generic',
45
+ 'government-document', 'grant', 'hearing', 'historical-work',
46
+ 'legal-case', 'legal-rule', 'magazine-article', 'manual', 'map',
47
+ 'multimedia', 'music', 'newspaper-article', 'pamphlet', 'patent',
48
+ 'personal-communication', 'proceedings', 'report', 'serial', 'slides',
49
+ 'software', 'software-code', 'software-container', 'software-executable',
50
+ 'software-virtual-machine', 'sound-recording', 'standard', 'statute',
51
+ 'thesis', 'unpublished', 'video', 'website'
136
52
  ].freeze
137
53
 
138
54
  # The [defined set of reference status types](https://citation-file-format.github.io/1.0.3/specifications/#/status-strings).
139
55
  REFERENCE_STATUS_TYPES = [
140
- 'abstract',
141
- 'advance-online',
142
- 'in-preparation',
143
- 'in-press',
144
- 'pre-print',
145
- 'submitted'
56
+ 'abstract', 'advance-online', 'in-preparation', 'in-press',
57
+ 'pre-print', 'submitted'
146
58
  ].freeze
147
59
 
148
60
  # :call-seq:
61
+ # new(title) -> Reference
149
62
  # new(title, type) -> Reference
150
63
  #
151
- # Create a new Reference with the supplied title and type. If type is not one of the [defined set of reference types](https://citation-file-format.github.io/1.0.3/specifications/#/reference-types), 'generic' will be used by default.
64
+ # Create a new Reference with the supplied title and, optionally, type.
65
+ # If type is not given, or is not one of the
66
+ # [defined set of reference types](https://citation-file-format.github.io/1.0.3/specifications/#/reference-types),
67
+ # 'generic' will be used by default.
152
68
  def initialize(param, *more)
153
- @authors = []
154
- @contact = []
155
- @editors = []
156
- @editors_series = []
157
- @recipients = []
158
- @senders = []
159
- @translators = []
160
-
161
- if Hash === param
162
- build_model(param)
69
+ if param.is_a?(Hash)
70
+ @fields = build_model(param)
163
71
  else
164
72
  @fields = Hash.new('')
165
- type = more[0].downcase
73
+ type = more[0] &&= more[0].downcase
166
74
  @fields['type'] = REFERENCE_TYPES.include?(type) ? type : 'generic'
167
75
  @fields['title'] = param
168
76
  end
169
77
 
170
78
  [
171
- 'keywords',
172
- 'patent-states'
79
+ 'authors', 'contact', 'editors', 'editors-series', 'keywords',
80
+ 'patent-states', 'recipients', 'senders', 'translators'
173
81
  ].each { |field| @fields[field] = [] if @fields[field].empty? }
174
82
  end
175
83
 
176
- # :call-seq:
177
- # authors -> Array
178
- #
179
- # Return the list of authors for this Reference. To add an author to the
180
- # list, use:
181
- #
182
- # ```
183
- # reference.authors << author
184
- # ```
185
- #
186
- # Authors can be a Person or Entity.
187
- def authors
188
- @authors
189
- end
190
-
191
- # :call-seq:
192
- # contact -> Array
193
- #
194
- # Return the list of contacts for this Reference. To add a contact to the
195
- # list, use:
196
- #
197
- # ```
198
- # reference.contact << contact
199
- # ```
200
- #
201
- # Contacts can be a Person or Entity.
202
- def contact
203
- @contact
204
- end
205
-
206
- # :call-seq:
207
- # editors -> Array
208
- #
209
- # Return the list of editors for this Reference. To add an editor to the
210
- # list, use:
211
- #
212
- # ```
213
- # reference.editors << editor
214
- # ```
215
- #
216
- # An editor can be a Person or Entity.
217
- def editors
218
- @editors
219
- end
220
-
221
- # :call-seq:
222
- # editors_series -> Array
223
- #
224
- # Return the list of series editors for this Reference. To add a series
225
- # editor to the list, use:
226
- #
227
- # ```
228
- # reference.editors_series << editor
229
- # ```
230
- #
231
- # An editor can be a Person or Entity.
232
- def editors_series
233
- @editors_series
234
- end
235
-
236
- # :call-seq:
237
- # recipients -> Array
238
- #
239
- # Return the list of recipients for this Reference. To add a recipient
240
- # to the list, use:
241
- #
242
- # ```
243
- # reference.recipients << recipient
244
- # ```
245
- #
246
- # Recipients can be a Person or Entity.
247
- def recipients
248
- @recipients
249
- end
250
-
251
- # :call-seq:
252
- # senders -> Array
253
- #
254
- # Return the list of senders for this Reference. To add a sender to the
255
- # list, use:
256
- #
257
- # ```
258
- # reference.senders << sender
259
- # ```
260
- #
261
- # Senders can be a Person or Entity.
262
- def senders
263
- @senders
264
- end
265
-
266
- # :call-seq:
267
- # translators -> Array
268
- #
269
- # Return the list of translators for this Reference. To add a translator
270
- # to the list, use:
271
- #
272
- # ```
273
- # reference.translators << translator
274
- # ```
275
- #
276
- # Translators can be a Person or Entity.
277
- def translators
278
- @translators
279
- end
280
-
281
84
  # :call-seq:
282
85
  # add_language language
283
86
  #
@@ -325,9 +128,7 @@ module CFF
325
128
  # Set the `date-accessed` field. If a non-Date object is passed in it will
326
129
  # be parsed into a Date.
327
130
  def date_accessed=(date)
328
- unless Date === date
329
- date = Date.parse(date)
330
- end
131
+ date = Date.parse(date) unless date.is_a?(Date)
331
132
 
332
133
  @fields['date-accessed'] = date
333
134
  end
@@ -338,9 +139,7 @@ module CFF
338
139
  # Set the `date-downloaded` field. If a non-Date object is passed in it will
339
140
  # be parsed into a Date.
340
141
  def date_downloaded=(date)
341
- unless Date === date
342
- date = Date.parse(date)
343
- end
142
+ date = Date.parse(date) unless date.is_a?(Date)
344
143
 
345
144
  @fields['date-downloaded'] = date
346
145
  end
@@ -351,9 +150,7 @@ module CFF
351
150
  # Set the `date-published` field. If a non-Date object is passed in it will
352
151
  # be parsed into a Date.
353
152
  def date_published=(date)
354
- unless Date === date
355
- date = Date.parse(date)
356
- end
153
+ date = Date.parse(date) unless date.is_a?(Date)
357
154
 
358
155
  @fields['date-published'] = date
359
156
  end
@@ -364,9 +161,7 @@ module CFF
364
161
  # Set the `date-released` field. If a non-Date object is passed in it will
365
162
  # be parsed into a Date.
366
163
  def date_released=(date)
367
- unless Date === date
368
- date = Date.parse(date)
369
- end
164
+ date = Date.parse(date) unless date.is_a?(Date)
370
165
 
371
166
  @fields['date-released'] = date
372
167
  end
@@ -409,43 +204,27 @@ module CFF
409
204
 
410
205
  # Override superclass #fields as References contain model parts too.
411
206
  def fields # :nodoc:
412
- ref = {}
413
-
414
- @fields.each do |field, value|
415
- if value.respond_to?(:map)
416
- ref[field] = value.map { |v| v.to_s } unless value.empty?
417
- else
418
- ref[field] = value.respond_to?(:fields) ? value.fields : value
419
- end
420
- end
421
-
422
207
  [
423
- ['authors', @authors],
424
- ['contact', @contact],
425
- ['editors', @editors],
426
- ['editors-series', @editors_series],
427
- ['recipients', @recipients],
428
- ['senders', @senders],
429
- ['translators', @translators]
430
- ].each do |field, var|
431
- ref[field] = expand_array_field(var) unless var.empty?
208
+ 'authors', 'contact', 'editors', 'editors-series', 'recipients',
209
+ 'senders', 'translators'
210
+ ].each do |field|
211
+ normalize_modelpart_array!(@fields[field])
432
212
  end
433
213
 
434
- ref
214
+ fields_to_hash(@fields)
435
215
  end
436
216
 
437
217
  private
438
218
 
439
- def build_model(fields)
440
- build_actor_collection(@authors, fields['authors'])
441
- build_actor_collection(@contact, fields['contact'])
442
- build_actor_collection(@editors, fields['editors'])
443
- build_actor_collection(@editors_series, fields['editors-series'])
444
- build_actor_collection(@recipients, fields['recipients'])
445
- build_actor_collection(@senders, fields['senders'])
446
- build_actor_collection(@translators, fields['translators'])
219
+ def build_model(fields) # :nodoc:
220
+ [
221
+ 'authors', 'contact', 'editors', 'editors-series', 'recipients',
222
+ 'senders', 'translators'
223
+ ].each do |field|
224
+ build_actor_collection!(fields[field])
225
+ end
447
226
 
448
- @fields = delete_from_hash(fields, 'authors', 'contact', 'editors', 'editors-series', 'recipients', 'senders', 'translators')
227
+ fields
449
228
  end
450
229
 
451
230
  public
@@ -453,6 +232,98 @@ module CFF
453
232
  # Some documentation of "hidden" methods is provided here, out of the
454
233
  # way of the main class code.
455
234
 
235
+ ##
236
+ # :method: authors
237
+ # :call-seq:
238
+ # authors -> Array
239
+ #
240
+ # Return the list of authors for this Reference. To add an author to the
241
+ # list, use:
242
+ #
243
+ # ```
244
+ # reference.authors << author
245
+ # ```
246
+ #
247
+ # Authors can be a Person or Entity.
248
+
249
+ ##
250
+ # :method: authors=
251
+ # :call-seq:
252
+ # authors = array_of_authors -> Array
253
+ #
254
+ # Replace the list of authors for this reference.
255
+ #
256
+ # Authors can be a Person or Entity.
257
+
258
+ ##
259
+ # :method: contact
260
+ # :call-seq:
261
+ # contact -> Array
262
+ #
263
+ # Return the list of contacts for this Reference. To add a contact to the
264
+ # list, use:
265
+ #
266
+ # ```
267
+ # reference.contact << contact
268
+ # ```
269
+ #
270
+ # Contacts can be a Person or Entity.
271
+
272
+ ##
273
+ # :method: contact=
274
+ # :call-seq:
275
+ # contact = array_of_contacts -> Array
276
+ #
277
+ # Replace the list of contacts for this reference.
278
+ #
279
+ # Contacts can be a Person or Entity.
280
+
281
+ ##
282
+ # :method: editors
283
+ # :call-seq:
284
+ # editors -> Array
285
+ #
286
+ # Return the list of editors for this Reference. To add an editor to the
287
+ # list, use:
288
+ #
289
+ # ```
290
+ # reference.editors << editor
291
+ # ```
292
+ #
293
+ # An editor can be a Person or Entity.
294
+
295
+ ##
296
+ # :method: editors=
297
+ # :call-seq:
298
+ # editors = array_of_editors -> Array
299
+ #
300
+ # Replace the list of editors for this reference.
301
+ #
302
+ # Editors can be a Person or Entity.
303
+
304
+ ##
305
+ # :method: editors_series
306
+ # :call-seq:
307
+ # editors_series -> Array
308
+ #
309
+ # Return the list of series editors for this Reference. To add a series
310
+ # editor to the list, use:
311
+ #
312
+ # ```
313
+ # reference.editors_series << editor
314
+ # ```
315
+ #
316
+ # An editor can be a Person or Entity.
317
+
318
+ ##
319
+ # :method: editors_series=
320
+ # :call-seq:
321
+ # editors_series = array_of_series_editors -> Array
322
+ #
323
+ # Replace the list of series editors for this reference.
324
+ #
325
+ # Series editors can be a Person or Entity.
326
+
456
327
  ##
457
328
  # :method: keywords
458
329
  # :call-seq:
@@ -498,5 +369,74 @@ module CFF
498
369
  # Replace the list of patent states for this reference.
499
370
  #
500
371
  # Patent states will be converted to Strings on output.
372
+
373
+ ##
374
+ # :method: recipients
375
+ # :call-seq:
376
+ # recipients -> Array
377
+ #
378
+ # Return the list of recipients for this Reference. To add a recipient
379
+ # to the list, use:
380
+ #
381
+ # ```
382
+ # reference.recipients << recipient
383
+ # ```
384
+ #
385
+ # Recipients can be a Person or Entity.
386
+
387
+ ##
388
+ # :method: recipients=
389
+ # :call-seq:
390
+ # recipients = array_of_recipients -> Array
391
+ #
392
+ # Replace the list of recipients for this reference.
393
+ #
394
+ # Recipients can be a Person or Entity.
395
+
396
+ ##
397
+ # :method: senders
398
+ # :call-seq:
399
+ # senders -> Array
400
+ #
401
+ # Return the list of senders for this Reference. To add a sender to the
402
+ # list, use:
403
+ #
404
+ # ```
405
+ # reference.senders << sender
406
+ # ```
407
+ #
408
+ # Senders can be a Person or Entity.
409
+
410
+ ##
411
+ # :method: senders=
412
+ # :call-seq:
413
+ # senders = array_of_senders -> Array
414
+ #
415
+ # Replace the list of senders for this reference.
416
+ #
417
+ # Senders can be a Person or Entity.
418
+
419
+ ##
420
+ # :method: translators
421
+ # :call-seq:
422
+ # translators -> Array
423
+ #
424
+ # Return the list of translators for this Reference. To add a translator
425
+ # to the list, use:
426
+ #
427
+ # ```
428
+ # reference.translators << translator
429
+ # ```
430
+ #
431
+ # Translators can be a Person or Entity.
432
+
433
+ ##
434
+ # :method: translators=
435
+ # :call-seq:
436
+ # translators = array_of_translators -> Array
437
+ #
438
+ # Replace the list of translators for this reference.
439
+ #
440
+ # Translators can be a Person or Entity.
501
441
  end
502
442
  end