bel 0.3.3 → 0.4.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +53 -8
  3. data/bel.gemspec +10 -15
  4. data/bin/bel +63 -4
  5. data/bin/bel2rdf.rb +1 -1
  6. data/bin/bel_compare.rb +1 -1
  7. data/bin/bel_parse.rb +1 -1
  8. data/bin/bel_rdfschema.rb +1 -1
  9. data/bin/bel_summarize.rb +1 -1
  10. data/bin/bel_upgrade.rb +1 -1
  11. data/lib/bel.rb +8 -10
  12. data/lib/bel/completion.rb +3 -2
  13. data/lib/bel/completion/value_match_rule.rb +10 -0
  14. data/lib/bel/evidence_model/citation.rb +101 -43
  15. data/lib/bel/evidence_model/evidence.rb +2 -2
  16. data/lib/bel/evidence_model/experiment_context.rb +1 -0
  17. data/lib/bel/evidence_model/metadata.rb +15 -2
  18. data/lib/bel/evidence_model/references.rb +10 -10
  19. data/lib/bel/json.rb +63 -0
  20. data/lib/bel/json/adapter/multi_json.rb +36 -0
  21. data/lib/bel/json/adapter/oj.rb +65 -0
  22. data/lib/bel/json/adapter/ruby_json.rb +28 -0
  23. data/lib/bel/json/reader.rb +9 -0
  24. data/lib/bel/json/writer.rb +9 -0
  25. data/lib/bel/libbel.rb +1 -4
  26. data/lib/bel/parser.rb +2 -2
  27. data/lib/bel/rdf_repository.rb +18 -0
  28. data/lib/bel/rdf_repository/plugins/memory.rb +28 -0
  29. data/lib/bel/rdf_repository/plugins/mongo.rb +28 -0
  30. data/lib/bel/resource.rb +24 -0
  31. data/lib/bel/resource/namespace.rb +122 -0
  32. data/lib/bel/resource/namespace_value.rb +69 -0
  33. data/lib/bel/resource/namespaces.rb +83 -0
  34. data/lib/bel/resource/search.rb +26 -0
  35. data/lib/bel/resource/search/api.rb +36 -0
  36. data/lib/bel/resource/search/search_result.rb +32 -0
  37. data/lib/bel/translate.rb +108 -0
  38. data/lib/bel/translator.rb +69 -0
  39. data/lib/bel/translator/plugins/bel_script.rb +36 -0
  40. data/lib/bel/translator/plugins/bel_script/bel_yielder.rb +144 -0
  41. data/lib/bel/translator/plugins/bel_script/evidence_yielder.rb +95 -0
  42. data/lib/bel/translator/plugins/bel_script/translator.rb +24 -0
  43. data/lib/bel/translator/plugins/jgf.rb +37 -0
  44. data/lib/bel/translator/plugins/jgf/translator.rb +160 -0
  45. data/lib/bel/translator/plugins/json_evidence.rb +38 -0
  46. data/lib/bel/translator/plugins/json_evidence/translator.rb +90 -0
  47. data/lib/bel/translator/plugins/rdf.rb +48 -0
  48. data/lib/bel/translator/plugins/rdf/bel_schema.rb +339 -0
  49. data/lib/bel/translator/plugins/rdf/monkey_patch.rb +310 -0
  50. data/lib/bel/translator/plugins/rdf/reader.rb +173 -0
  51. data/lib/bel/translator/plugins/rdf/translator.rb +40 -0
  52. data/lib/bel/translator/plugins/rdf/writer.rb +45 -0
  53. data/lib/bel/translator/plugins/xbel.rb +36 -0
  54. data/lib/bel/translator/plugins/xbel/evidence_handler.rb +468 -0
  55. data/lib/bel/translator/plugins/xbel/evidence_yielder.rb +24 -0
  56. data/lib/bel/translator/plugins/xbel/translator.rb +24 -0
  57. data/lib/bel/translator/plugins/xbel/xbel_yielder.rb +414 -0
  58. data/lib/bel/vendor/little-plugger.rb +323 -0
  59. data/lib/bel/version.rb +1 -1
  60. metadata +44 -158
  61. data/lib/bel/extension.rb +0 -37
  62. data/lib/bel/extension_format.rb +0 -207
  63. data/lib/bel/extensions/bel.rb +0 -258
  64. data/lib/bel/extensions/jgf.rb +0 -219
  65. data/lib/bel/extensions/json/jrjackson.rb +0 -31
  66. data/lib/bel/extensions/json/json.rb +0 -133
  67. data/lib/bel/extensions/json/multi_json.rb +0 -29
  68. data/lib/bel/extensions/json/oj.rb +0 -68
  69. data/lib/bel/extensions/json/ruby_json.rb +0 -29
  70. data/lib/bel/extensions/rdf/bel_rdf.rb +0 -338
  71. data/lib/bel/extensions/rdf/rdf.rb +0 -584
  72. data/lib/bel/extensions/xbel.rb +0 -923
  73. data/lib/bel/format.rb +0 -58
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c3d7813a2ca00e8838fad4dd0129d2952dee3c8a
4
- data.tar.gz: 4dca498c75de99c526c01cf6fc2209a3c6cb3c3f
3
+ metadata.gz: b3ec967adaa542f9d53a44d81b392aedf8e83977
4
+ data.tar.gz: 57befbff871e8d293eaef7b44b0cb928e38e5f45
5
5
  SHA512:
6
- metadata.gz: 7f3e8ec10f2633af8bf52073d0f014e228a3c304cc1b1fe3e71ccf098f3974b7aea6f26ed7d86020ecb0207bd3b5f813f645d5986b135eb3d68d06ad1ace2654
7
- data.tar.gz: a54fa94761b80e35edf4a75bf6e836d8914228c540c97dc40ad9ac741485304338f99184b2819c2f33172b48b252596fe7502b8fe76718368d95e479fbcabd07
6
+ metadata.gz: 6598b80261a35fa182cc0e25cd76ff952614e99c7ea6697f09b097e1c1172bd31b30a0907fb31a963d37a8e6f3662247550655752d6835df15961a26644f5ddf
7
+ data.tar.gz: 1894266854e10a8481b8fe473dd2803dd4fa5d90079d048985236ca27c6466c82af878f7b574c758a273cd42bd56bfbf62d020e2ab3922427b35923fa8da2958
data/README.md CHANGED
@@ -1,5 +1,4 @@
1
- bel ruby
2
- ========
1
+ # bel ruby
3
2
 
4
3
  [![Gem Version](https://badge.fury.io/rb/bel.svg)](http://badge.fury.io/rb/bel)
5
4
 
@@ -32,18 +31,65 @@ Install / Build: See [INSTALL](INSTALL.md).
32
31
 
33
32
  A changelog is maintained at [CHANGELOG][CHANGELOG].
34
33
 
35
- branches
36
- --------
34
+ ## development
35
+
36
+ Developing on bel.rb requires a few steps.
37
+
38
+ 1. [Install Ruby](INSTALL_RUBY.md).
39
+ 2. Clone this repository:
40
+
41
+ ```
42
+ git@github.com:OpenBEL/bel.rb.git
43
+ ```
44
+
45
+ 3. Change to repository directory. Install bel.rb's dependencies (including development dependencies):
46
+
47
+ ```
48
+ cd bel.rb; ./scripts/gem-install-devdeps.sh
49
+ ```
50
+
51
+ 4. Build C extension (i.e. [libbel parser](https://github.com/OpenBEL/libbel)) using Rake:
52
+
53
+ ```
54
+ rake compile
55
+ ```
56
+
57
+ This will build the C shared library you will need to use the C-based parser.
58
+
59
+ Note: Windows users will need to install the [RubyInstaller DevKit](https://github.com/oneclick/rubyinstaller/wiki/Development-Kit) to build the C extension.
60
+
61
+ ### isolated development
62
+
63
+ During development, it is recommended to isolate bel.rb from any existing user
64
+ or system gems. This will help keep gems used during development entirely
65
+ separate from all others.
66
+
67
+ To accomplish this, set ``BR_ISOLATE`` to ``"yes"`` in ``env.sh.custom``, at
68
+ the root of the bel.rb tree:
69
+
70
+ ```bash
71
+ export BR_ISOLATE="yes"
72
+ ```
73
+
74
+
75
+ ## branches
37
76
 
38
77
  - master branch
78
+ - Contains stable code. Releases are created from this branch using a tag (e.g. 0.3.3).
39
79
  - [![Travis CI Build](https://travis-ci.org/OpenBEL/bel.rb.svg?branch=master)](https://travis-ci.org/OpenBEL/bel.rb)
40
80
 
41
81
  - next branch
82
+ - Contains unstable code. Commits should be merged into master after it stabilizes.
42
83
  - [![Build Status for next branch](https://travis-ci.org/OpenBEL/bel.rb.svg?branch=next)](https://travis-ci.org/OpenBEL/bel.rb)
43
84
 
85
+ ## contributors
86
+
87
+ - [@abargnesi](https://github.com/abargnesi) (Maintainer)
88
+ - [@nbargnesi](https://github.com/nbargnesi) (Maintainer)
89
+ - [@ncatlett](https://github.com/ncatlett) (Contributor)
90
+ - [@wshayes](https://github.com/wshayes) (Contributor)
44
91
 
45
- executable commands
46
- -------------------
92
+ ## executable commands
47
93
 
48
94
  **bel**: A single executable command with subcommands.
49
95
 
@@ -154,8 +200,7 @@ executable commands
154
200
  ```
155
201
 
156
202
 
157
- api examples
158
- ------------
203
+ ## api examples
159
204
 
160
205
  **Use OpenBEL namespaces from the latest release.**
161
206
 
@@ -55,22 +55,17 @@ Gem::Specification.new do |spec|
55
55
  spec.extensions << 'ext/mri/extconf.rb'
56
56
  spec.required_ruby_version = '>= 2.0.0'
57
57
 
58
- # runtime
59
- spec.add_dependency 'ffi', '1.9.8'
58
+ spec.add_runtime_dependency 'ffi', '1.9.8'
60
59
 
61
- # test rdf functionality
62
- spec.add_development_dependency 'addressable', '~> 2.3'
63
- spec.add_development_dependency 'rdf', '~> 1.1'
64
- spec.add_development_dependency 'rdf-turtle', '~> 1.1'
65
- spec.add_development_dependency 'uuid', '~> 2.3'
66
-
67
- # development gems
68
- spec.add_development_dependency 'minitest', '~> 5.7'
69
- spec.add_development_dependency 'rake', '~> 10.4'
70
- spec.add_development_dependency 'rake-compiler', '~> 0.9'
71
- spec.add_development_dependency 'rdoc', '~> 4.2'
72
- spec.add_development_dependency 'rspec', '~> 3.2'
73
- spec.add_development_dependency 'yard', '~> 0.8'
60
+ # Example post-install message.
61
+ #
62
+ # These aren't real BEL-related gems, but if we can sneak the names passed
63
+ # abargnesi, maybe one day... ;)
64
+ # spec.post_install_message = %q(
65
+ # -- bel.rb notice --
66
+ # Install any of these additional gems for more functionality:
67
+ # bel-rdf, clapper, carillon, peal, ...
68
+ # )
74
69
  end
75
70
  # vim: ts=2 sw=2:
76
71
  # encoding: utf-8
data/bin/bel CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
2
+ $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
3
3
  require 'erb'
4
4
  require 'bel'
5
5
  require 'bel/vendor/trollop'
@@ -260,7 +260,7 @@ Subcommands:
260
260
 
261
261
  from_format, to_format = ARGV
262
262
 
263
- from = BEL::Extension::Format.formatters(from_format)
263
+ from = BEL.translator(from_format)
264
264
  unless from
265
265
  $stderr.puts(
266
266
  from_format ?
@@ -271,7 +271,7 @@ Subcommands:
271
271
  Trollop::educate
272
272
  end
273
273
 
274
- to = BEL::Extension::Format.formatters(to_format)
274
+ to = BEL.translator(to_format)
275
275
  unless to
276
276
  $stderr.puts(
277
277
  to_format ?
@@ -283,7 +283,7 @@ Subcommands:
283
283
  end
284
284
 
285
285
  begin
286
- BEL::Format.translate(input_io, from_format, to_format, $stdout)
286
+ BEL.translate(input_io, from_format, to_format, $stdout)
287
287
  ensure
288
288
  $stdout.close
289
289
  end
@@ -326,6 +326,65 @@ Subcommands:
326
326
  require_relative 'bel_upgrade'
327
327
  end
328
328
  end
329
+
330
+ class PluginsCommand
331
+
332
+ def initialize(global_options)
333
+ @global_options = global_options
334
+ end
335
+
336
+ def run
337
+ options = Trollop::options do
338
+ synopsis "Interact with available plugins."
339
+ usage "[OPTIONS]... plugins [OPTIONS]"
340
+ opt :list, 'Lists available plugins',
341
+ :long => :list,
342
+ :short => :l,
343
+ :default => true
344
+ end
345
+
346
+ if options[:list]
347
+ $stdout.puts "RDF Repository plugins"
348
+ $stdout.puts "----------------------"
349
+ $stdout.puts
350
+ BEL::RdfRepository.plugins.
351
+ values.
352
+ sort_by { |plugin| plugin.name}.
353
+ each do |plugin|
354
+ $stdout.puts %Q{
355
+ Name: #{plugin.name}
356
+ Description: #{plugin.description}
357
+ }.gsub(%r{^\s+}, ' ')
358
+ end
359
+
360
+ $stdout.puts "Resource Search plugins"
361
+ $stdout.puts "-----------------------"
362
+ $stdout.puts
363
+ BEL::Resource::Search.plugins.
364
+ values.
365
+ sort_by { |plugin| plugin.name}.
366
+ each do |plugin|
367
+ $stdout.puts %Q{
368
+ Name: #{plugin.name}
369
+ Description: #{plugin.description}
370
+ }.gsub(%r{^\s+}, ' ')
371
+ end
372
+
373
+ $stdout.puts "Translator plugins"
374
+ $stdout.puts "------------------"
375
+ $stdout.puts
376
+ BEL::Translator.plugins.
377
+ values.
378
+ sort_by { |plugin| plugin.name}.
379
+ each do |plugin|
380
+ $stdout.puts %Q{
381
+ Name: #{plugin.name}
382
+ Description: #{plugin.description}
383
+ }.gsub(%r{^\s+}, ' ')
384
+ end
385
+ end
386
+ end
387
+ end
329
388
  end
330
389
  end
331
390
 
@@ -13,7 +13,7 @@
13
13
  # Format option
14
14
  # usage: bel2rdf --bel [FILE] --format [ntriples | nquads | turtle]
15
15
 
16
- $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
16
+ $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
17
17
  require 'bel'
18
18
  require 'optparse'
19
19
  require 'set'
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # vim: ts=2 sw=2
3
3
 
4
- $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
4
+ $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
5
5
  require 'optparse'
6
6
  require 'bel'
7
7
  include BEL::Language
@@ -7,7 +7,7 @@
7
7
  # From standard in
8
8
  # usage: echo "<BEL DOCUMENT STRING>" | bel_parse
9
9
 
10
- $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
10
+ $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
11
11
  require 'bel'
12
12
  require 'optparse'
13
13
 
@@ -2,7 +2,7 @@
2
2
  # bel_rdfschema: Dump RDF schema for BEL.
3
3
  # usage: bel_rdfschema --format [ntriples | nquads | turtle]
4
4
 
5
- $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
5
+ $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
6
6
  require 'bel'
7
7
  require 'optparse'
8
8
  require 'set'
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # vim: ts=2 sw=2
3
3
 
4
- $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
4
+ $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
5
5
  require 'bel'
6
6
  require 'csv'
7
7
  require 'optparse'
@@ -7,7 +7,7 @@
7
7
  # From standard in
8
8
  # usage: echo "<BEL DOCUMENT STRING>" | bel_upgrade -c file.json
9
9
 
10
- $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
10
+ $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
11
11
  require 'bel'
12
12
  require 'json'
13
13
  require 'optparse'
data/lib/bel.rb CHANGED
@@ -1,12 +1,15 @@
1
1
  require_relative 'bel/version'
2
+ require_relative 'bel/vendor/little-plugger'
2
3
  require_relative 'bel/language'
3
4
  require_relative 'bel/namespace'
4
5
  require_relative 'bel/util'
5
6
 
6
- require_relative 'bel/extension'
7
- require_relative 'bel/extension_format'
8
7
  require_relative 'bel/evidence_model'
9
- require_relative 'bel/format'
8
+ require_relative 'bel/translator'
9
+ require_relative 'bel/translate'
10
+
11
+ require_relative 'bel/rdf_repository'
12
+ require_relative 'bel/resource'
10
13
 
11
14
  require_relative 'bel/script'
12
15
 
@@ -17,13 +20,8 @@ require_relative 'bel/completion'
17
20
  include BEL::Language
18
21
  include BEL::Namespace
19
22
 
20
- BEL::Extension.load_extension('jgf', 'json/json', 'bel', 'xbel')
21
-
22
- begin
23
- BEL::Extension.load_extension('rdf/rdf')
24
- rescue LoadError => e
25
- # No RDF support.
26
- # TODO Report extension load failure.
23
+ module BEL
24
+ extend BEL::Translate::ClassMethods
27
25
  end
28
26
  # vim: ts=2 sw=2:
29
27
  # encoding: utf-8
@@ -13,7 +13,8 @@ module BEL
13
13
  # return all BEL functions as possible completions.
14
14
  #
15
15
  # If +search+ is +nil+ then namespace values will not be provided as
16
- # completion. +search+ is expected to implement {IdentifierSearch}.
16
+ # completion. +search+ is expected to provide +#search+ and
17
+ # +#search_namespace+ methods.
17
18
  #
18
19
  # If +position+ is +nil+ then its assumed to be the last index of
19
20
  # +bel_expression+ otherwise the +to_i+ method is called.
@@ -23,7 +24,7 @@ module BEL
23
24
  #
24
25
  # @param bel_expression [responds to #to_s] the bel expression to
25
26
  # complete on
26
- # @param search [IdentifierSearch] the search object used to
27
+ # @param search [#search_namespace, #search] the search object used to
27
28
  # provide namespace value completions
28
29
  # @param position [responds to #to_i] the position to complete from
29
30
  # @return [Array<Completion>]
@@ -0,0 +1,10 @@
1
+ module BEL
2
+ module Completion
3
+
4
+ class ValueMatch
5
+
6
+ def call(ast)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -1,46 +1,40 @@
1
1
  module BEL
2
2
  module Model
3
3
 
4
- # A Citation provides a reference to the resource containing the
5
- # {Evidence} information. The fields are defined as:
4
+ # A Citation describes a cited reference which {Evidence} is derived from.
6
5
  #
7
- # - +date+
8
- # - The date represents when the article was published.
9
- # - +authors+
10
- # - The authors refer to the authors of the article.
11
- #
12
- # @attr [String] type the type of the article commonly defined by
13
- # +"PubMed"+, +"Journal"+, +"Book"+, or +"Online Resource"+
14
- # @attr [String] name the name of the article
15
- # @attr [String] id the identifier of the article. For example, for a
16
- # +"PubMed"+ type the identifier is the PMID (i.e. 12102192)
17
- # @attr [String] date the date when the article was published
18
- # @attr [String] authors the authors of the article
19
- # @attr [String] comment a comment on the citation
20
- class Citation < Struct.new(
21
- :type,
22
- :name,
23
- :id,
24
- :date,
25
- :authors,
26
- :comment
27
- )
6
+ # @attr [String] type the type of resource the cited material appears in
7
+ # (e.g. PubMed, Journal, Book, Online Resource, etc...)
8
+ # @attr [String] name the name of the cited resource
9
+ # @attr [String] id the unique identifier for the cited resource. For
10
+ # example, a +"PubMed"+ type should have a PMID (i.e. 12102192).
11
+ # @attr [String] date the date the resource was published
12
+ # @attr [String] authors the authors of the resource
13
+ # @attr [String] comment an additional comment related to this resource
14
+ class Citation
28
15
 
29
- # Creates a {Citation} struct from a +Hash+.
30
- # @param [Hash] fields the citation fields to populate based on hash
31
- # keys
32
- # @example Create a minimal {Citation}.
33
- # Citation.create(
34
- # {
35
- # :type => 'PubMed',
36
- # :name => 'Biocompatibility study of biological tissues fixed
37
- # by a natural compound (reuterin) produced by
38
- # Lactobacillus reuteri.',
39
- # :id => '12102192'
40
- # }
16
+ MEMBER_ORDER = %i(type name id date authors comment)
17
+
18
+ attr_accessor(*MEMBER_ORDER)
19
+
20
+ # Creates a {Citation} object from variable arguments.
21
+ #
22
+ # @param [Array<Object>] args Argument array of Object; If the array
23
+ # contains a single value then it is expected to either respond
24
+ # to +:each+ (according to #MEMBER_ORDER) or +:each_pair+
25
+ # (keys matching that of #MEMBER_ORDER). If the array has
26
+ # multiple values then they are set sequentially according to
27
+ # #MEMBER_ORDER.
28
+ # @example Create an empty {Citation}.
29
+ # Citation.new
30
+ # @example Create a minimal {Citation} by positional members.
31
+ # Citation.new('PubMed', 'Biocompatibility study of...', '12102192')
32
+ # @example Create a minimal {Citation} by positional members in array.
33
+ # Citation.new(
34
+ # ['PubMed', 'Biocompatibility study of...', '12102192']
41
35
  # )
42
- # @example Create a full {Citation}.
43
- # Citation.create(
36
+ # @example Create a full {Citation} by hash using keys for members.
37
+ # Citation.new(
44
38
  # {
45
39
  # :type => 'PubMed',
46
40
  # :name => 'Biocompatibility study of biological tissues fixed
@@ -52,17 +46,81 @@ module BEL
52
46
  # :comment => 'This article is primary research.'
53
47
  # }
54
48
  # )
55
- def self.create(fields = {})
56
- citation = Citation.new
57
- (Citation.members & fields.keys).each { |member|
58
- citation.send(:"#{member}=", fields[member])
59
- }
60
- citation
49
+ def initialize(*args)
50
+ return if !args || args.empty?
51
+
52
+ if args.length == 1
53
+ enumerable = args.first
54
+ if enumerable.respond_to? :each_pair
55
+ (MEMBER_ORDER & enumerable.keys).each do |member|
56
+ self.send(:"#{member}=", enumerable[member])
57
+ end
58
+ elsif enumerable.respond_to? :each
59
+ MEMBER_ORDER.zip(enumerable.each).each do |member, value|
60
+ self.send(:"#{member}=", value)
61
+ end
62
+ end
63
+ else
64
+ (MEMBER_ORDER & args).each do |member|
65
+ self.send(:"#{member}=", hash[member])
66
+ end
67
+ end
68
+ end
69
+
70
+ # Returns the +Array+ of +String+ authors.
71
+ #
72
+ # @return [Array<String>] array of authors
73
+ def authors
74
+ @authors
75
+ end
76
+
77
+ # Sets the authors value.
78
+ #
79
+ # @param [#each, #each_pair, #to_s] authors an authors value
80
+ def authors=(authors)
81
+ @authors = convert_authors(authors)
61
82
  end
62
83
 
84
+ # Returns whether the citation has enough pertinent information to be
85
+ # considered valid.
86
+ #
87
+ # @return [true, false] whether the citation is valid
63
88
  def valid?
64
89
  type != nil && id != nil && name != nil
65
90
  end
91
+
92
+ # Returns a +Hash+ of the citation members accoring to #MEMBER_ORDER.
93
+ #
94
+ # @return [Hash] citation +Hash+
95
+ def to_h
96
+ MEMBER_ORDER.reduce({}) { |hash, member|
97
+ hash[member] = self.send(member)
98
+ hash
99
+ }
100
+ end
101
+
102
+ def to_a
103
+ MEMBER_ORDER.reduce([]) { |array, member|
104
+ array << self.send(member)
105
+ array
106
+ }
107
+ end
108
+
109
+ private
110
+
111
+ def convert_authors(authors)
112
+ return nil unless authors
113
+
114
+ if authors.respond_to? :to_a
115
+ authors.to_a.map(&:to_s)
116
+ elsif authors.respond_to? :each
117
+ @authors = authors.each.to_a.map(&:to_s)
118
+ elsif authors.respond_to? :to_s
119
+ authors.to_s.split('|').map(&:strip)
120
+ else
121
+ raise ArgumentError.new("authors must be a string-like or iterable")
122
+ end
123
+ end
66
124
  end
67
125
  end
68
126
  end