relaton-bib 1.0.0 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2cf0aacc339840ecc4607d6b87e625eaef60ba12ab0fbeffba5876898518f138
4
- data.tar.gz: e41a599b99baaa6d1002cd3ad13803bcffeaa6949840a8cd757db3689716f06b
3
+ metadata.gz: 1f046b9f9c341d92cec95e89a817afea83133a322255f259c34c869aafcea60c
4
+ data.tar.gz: e9535bc5707436472ef9986faa9e429d2c451c94bc9b46f0ed10b21b8304dc41
5
5
  SHA512:
6
- metadata.gz: 4f8e1bfe3c6ca8d2ec19733f7ea0f018bae2a102ad92d05bb0983ddf9b7e8715c86c56980ffa106500c2a6971a625143cb6bec2ae9b9a2dd0190fc8b605539c1
7
- data.tar.gz: 721ba6235c7cabc380825ce184f0b2874f1ba519b2f6b9dc44fea52ae061b3bdd18ab56c5db94698535b8db10fe365a88aaf23bcd32a25fa5ce7de96bb8a93b6
6
+ metadata.gz: 85b19d11a3eef57448df18fee645c53539fc485cf90f6b07b303311bf0d7dd2f4666c1bacfeae3f15aafc372cc93a60bfbcb3993783cba3103dd018633607633
7
+ data.tar.gz: 6a91bcba71ca9d070eb906a827ee8b5be314b888691e1f4849081163efc1c9e2b2218ac3d03e791569852cfa49ec9c2d1af7e8e16a45ff2facbf2af9b1c32824
@@ -13,7 +13,8 @@ module RelatonBib
13
13
  # @param date [String]
14
14
  # @return [Date, NilClass]
15
15
  def parse_date(sdate)
16
- if /(?<date>\w+\s\d{4})/ =~ sdate # February 2012
16
+ if sdate.is_a?(Date) then sdate
17
+ elsif /(?<date>\w+\s\d{4})/ =~ sdate # February 2012
17
18
  Date.strptime(date, "%B %Y")
18
19
  elsif /(?<date>\w+\s\d{1,2},\s\d{4})/ =~ sdate # February 11, 2012
19
20
  Date.strptime(date, "%B %d, %Y")
@@ -21,8 +22,7 @@ module RelatonBib
21
22
  Date.parse(date)
22
23
  elsif /(?<date>\d{4}-\d{2})/ =~ sdate # 2012-02
23
24
  Date.strptime date, "%Y-%m"
24
- elsif /(?<date>\d{4})/ =~ sdate # 2012
25
- Date.strptime date, "%Y"
25
+ elsif /(?<date>\d{4})/ =~ sdate then Date.strptime date, "%Y" # 2012
26
26
  end
27
27
  end
28
28
  end
@@ -83,7 +83,7 @@ module RelatonBib
83
83
  # @return [RelatonBib::DocumentStatus, NilClass]
84
84
  attr_reader :status
85
85
 
86
- # @return [RelatonBib::CopyrightAssociation, NilClass]
86
+ # @return [Array<RelatonBib::CopyrightAssociation>]
87
87
  attr_reader :copyright
88
88
 
89
89
  # @return [RelatonBib::DocRelationCollection]
@@ -141,10 +141,11 @@ module RelatonBib
141
141
  # @param fetched [Date, NilClass] default nil
142
142
  # @param keyword [Array<String>]
143
143
  #
144
- # @param copyright [Hash, RelatonBib::CopyrightAssociation, NilClass]
145
- # @option copyright [Hash, RelatonBib::ContributionInfo] :owner
146
- # @option copyright [String] :form
144
+ # @param copyright [Array<Hash, RelatonBib::CopyrightAssociation>]
145
+ # @option copyright [Array<Hash, RelatonBib::ContributionInfo>] :owner
146
+ # @option copyright [String] :from
147
147
  # @option copyright [String, NilClass] :to
148
+ # @option copyright [String, NilClass] :scope
148
149
  #
149
150
  # @param date [Array<Hash>]
150
151
  # @option date [String] :type
@@ -202,11 +203,8 @@ module RelatonBib
202
203
  a.is_a?(Hash) ? FormattedString.new(a) : a
203
204
  end
204
205
 
205
- if args[:copyright]
206
- @copyright = if args[:copyright].is_a?(Hash)
207
- CopyrightAssociation.new args[:copyright]
208
- else args[:copyright]
209
- end
206
+ @copyright = args.fetch(:copyright, []).map do |c|
207
+ c.is_a?(Hash) ? CopyrightAssociation.new(c) : c
210
208
  end
211
209
 
212
210
  @docidentifier = args[:docid] || []
@@ -308,7 +306,7 @@ module RelatonBib
308
306
  hash["formattedref"] = formattedref.to_hash if formattedref
309
307
  hash["abstract"] = single_element_array(abstract) if abstract&.any?
310
308
  hash["docstatus"] = status.to_hash if status
311
- hash["copyright"] = copyright.to_hash if copyright
309
+ hash["copyright"] = single_element_array(copyright) if copyright&.any?
312
310
  hash["relation"] = single_element_array(relation) if relation&.any?
313
311
  hash["series"] = single_element_array(series) if series&.any?
314
312
  hash["medium"] = medium.to_hash if medium
@@ -530,7 +528,7 @@ module RelatonBib
530
528
  script.each { |s| builder.script s }
531
529
  abstract.each { |a| builder.abstract { a.to_xml(builder) } }
532
530
  status&.to_xml builder
533
- copyright&.to_xml builder
531
+ copyright&.each { |c| c.to_xml builder }
534
532
  relation.each { |r| r.to_xml builder, **opts }
535
533
  series.each { |s| s.to_xml builder }
536
534
  medium&.to_xml builder
@@ -147,17 +147,16 @@ module RelatonBib
147
147
  # @param bibtex [BibTeX::Entry]
148
148
  # @return [Array<RelatonBib::BiblioNote>]
149
149
  def fetch_note(bibtex)
150
- note = []
151
- note << BiblioNote.new(type: "annote", content: bibtex.annote.to_s) if bibtex["annote"]
152
-
153
- if bibtex["howpublished"]
154
- note << BiblioNote.new(type: "howpublished", content: bibtex.howpublished.to_s)
150
+ bibtex.select do |k, _v|
151
+ %i[annote howpublished comment note content].include? k
152
+ end.reduce([]) do |mem, note|
153
+ type = case note[0]
154
+ when :note then nil
155
+ when :content then "tableOfContents"
156
+ else note[0].to_s
157
+ end
158
+ mem << BiblioNote.new(type: type, content: note[1].to_s)
155
159
  end
156
-
157
- note << BiblioNote.new(type: "comment", content: bibtex.comment.to_s) if bibtex["comment"]
158
- note << BiblioNote.new(content: bibtex.note.to_s) if bibtex["note"]
159
- note << BiblioNote.new(type: "tableOfContents", content: bibtex["content"]) if bibtex["content"]
160
- note
161
160
  end
162
161
 
163
162
  # @param bibtex [BibTeX::Entry]
@@ -172,16 +171,19 @@ module RelatonBib
172
171
  # @param bibtex [BibTeX::Entry]
173
172
  # @return [Array<RelatonBib::BibItemLocality>]
174
173
  def fetch_extent(bibtex)
175
- extent = []
176
- extent << BibItemLocality.new("chapter", bibtex.chapter.to_s) if bibtex["chapter"]
177
-
178
- if bibtex["pages"]
179
- from, to = bibtex.pages.to_s.split "-"
180
- extent << BibItemLocality.new("page", from, to)
174
+ bibtex.select do |k, _v|
175
+ %i[chapter pages volume].include? k
176
+ end.reduce([]) do |mem, loc|
177
+ if loc[0] == :pages
178
+ type = "page"
179
+ from, to = loc[1].to_s.split "-"
180
+ else
181
+ type = loc[0].to_s
182
+ from = loc[1].to_s
183
+ to = nil
184
+ end
185
+ mem << BibItemLocality.new(type, from, to)
181
186
  end
182
-
183
- extent << BibItemLocality.new("volume", bibtex.volume.to_s) if bibtex["volume"]
184
- extent
185
187
  end
186
188
 
187
189
  # @param bibtex [BibTeX::Entry]
@@ -192,7 +194,7 @@ module RelatonBib
192
194
  series << Series.new(
193
195
  type: "journal",
194
196
  title: TypedTitleString.new(content: bibtex.journal.to_s),
195
- number: bibtex["number"]&.to_s
197
+ number: bibtex["number"]&.to_s,
196
198
  )
197
199
  end
198
200
 
@@ -1,29 +1,41 @@
1
1
  module RelatonBib
2
2
  # Copyright association.
3
3
  class CopyrightAssociation
4
+ include RelatonBib
5
+
4
6
  # @return [Date]
5
7
  attr_reader :from
6
8
 
7
9
  # @return [Date, NilClass]
8
10
  attr_reader :to
9
11
 
10
- # @return [RelatonBib::ContributionInfo]
12
+ # @return [String, NilClass]
13
+ attr_reader :scope
14
+
15
+ # @return [Array<RelatonBib::ContributionInfo>]
11
16
  attr_reader :owner
12
17
 
13
- # @param owner [Hash, RelatonBib::ContributionInfo] contributor
18
+ # rubocop:disable Metrics/AbcSize
19
+
20
+ # @param owner [Array<Hash, RelatonBib::ContributionInfo>] contributor
14
21
  # @option owner [String] :name
15
22
  # @option owner [String] :abbreviation
16
23
  # @option owner [String] :url
17
24
  # @param from [String] date
18
25
  # @param to [String, NilClass] date
19
- def initialize(owner:, from:, to: nil)
20
- @owner = if owner.is_a?(Hash)
21
- ContributionInfo.new entity: Organization.new(owner)
22
- else owner
23
- end
26
+ # @param scope [String, NilClass]
27
+ def initialize(owner:, from:, to: nil, scope: nil)
28
+ unless owner.any?
29
+ raise ArgumentError, "at least one owner should exist."
30
+ end
31
+
32
+ @owner = owner.map do |o|
33
+ o.is_a?(Hash) ? ContributionInfo.new(entity: Organization.new(o)) : o
34
+ end
24
35
 
25
36
  @from = Date.strptime(from.to_s, "%Y") if from.to_s =~ /\d{4}/
26
37
  @to = Date.strptime(to.to_s, "%Y") unless to.to_s.empty?
38
+ @scope = scope
27
39
  end
28
40
 
29
41
  # @param builder [Nokogiri::XML::Builder]
@@ -31,14 +43,21 @@ module RelatonBib
31
43
  builder.copyright do
32
44
  builder.from from ? from.year : "unknown"
33
45
  builder.to to.year if to
34
- builder.owner { owner.to_xml builder }
46
+ owner.each { |o| builder.owner { o.to_xml builder } }
47
+ builder.scope scope if scope
35
48
  end
36
49
  end
50
+ # rubocop:enable Metrics/AbcSize
37
51
 
38
52
  # @return [Hash]
39
53
  def to_hash
40
- hash = { "owner" => owner.to_hash["organization"], "from" => from.year.to_s }
54
+ owners = single_element_array(owner.map { |o| o.to_hash["organization"] })
55
+ hash = {
56
+ "owner" => owners,
57
+ "from" => from.year.to_s,
58
+ }
41
59
  hash["to"] = to.year.to_s if to
60
+ hash["scope"] = scope if scope
42
61
  hash
43
62
  end
44
63
  end
@@ -1,24 +1,27 @@
1
1
  module RelatonBib
2
- # module DocumentRelationType
3
- # PARENT = 'parent'
4
- # CHILD = 'child'
5
- # OBSOLETES = 'obsoletes'
6
- # UPDATES = 'updates'
7
- # COMPLEMENTS = 'complements'
8
- # DERIVED_FORM = 'derivedForm'
9
- # ADOPTED_FORM = 'adoptedForm'
10
- # EQUIVALENT = 'equivalent'
11
- # IDENTICAL = 'identical'
12
- # NONEQUIVALENT = 'nonequivalent'
13
- # end
14
-
15
2
  # Documett relation
16
3
  class DocumentRelation
17
4
  include RelatonBib
18
5
 
6
+ TYPES = %w[
7
+ includes includedIn hasPart partOf merges mergedInto splits splitInto
8
+ instance hasInstance exemplarOf hasExemplar manifestationOf
9
+ hasManifestation reproductionOf hasReproduction reprintOf hasReprint
10
+ expressionOf hasExpression translatedFrom hasTranslation arrangementOf
11
+ hasArrangement abridgementOf hasAbridgement annotationOf hasAnnotation
12
+ draftOf hasDraft editionOf hasEdition updates updatedBy derivedFrom
13
+ derives describes describedBy catalogues cataloguedBy hasSuccessor
14
+ successorOf adaptedFrom hasAdaptation adoptedFrom adoptedAs reviewOf
15
+ hasReview commentaryOf hasCommentary related complements complementOf
16
+ obsoletes obsoletedBy cited isCitedIn
17
+ ].freeze
18
+
19
19
  # @return [String]
20
20
  attr_reader :type
21
21
 
22
+ # @return [RelatonBib::FormattedString, NilClass]
23
+ attr_reader :description
24
+
22
25
  # @return [String]
23
26
  # attr_reader :identifier, :url
24
27
 
@@ -28,35 +31,49 @@ module RelatonBib
28
31
  # @return [Array<RelatonBib::Locality, RelatonBib::LocalityStack>]
29
32
  attr_reader :locality
30
33
 
31
- # @return [Array<RelatonBib::SourceLocality, RelatonBib::SourceLocalityStack>]
34
+ # @return [Array<RelatonBib::SourceLocality,
35
+ # RelatonBib::SourceLocalityStack>]
32
36
  attr_reader :source_locality
33
37
 
34
38
  # @param type [String]
35
- # @param bibitem [RelatonBib::BibliographicItem, RelatonIso::IsoBibliographicItem]
39
+ # @parma description [RelatonBib::FormattedString, NilClass]
40
+ # @param bibitem [RelatonBib::BibliographicItem,
41
+ # RelatonIso::IsoBibliographicItem]
36
42
  # @param locality [Array<RelatonBib::Locality, RelatonBib::LocalityStack>]
37
- # @param source_locality [Array<RelatonBib::SourceLocality, RelatonBib::SourceLocalityStack>]
38
- def initialize(type:, bibitem:, locality: [], source_locality: [])
39
- type = "obsoletes" if type == "Now withdrawn"
43
+ # @param source_locality [Array<RelatonBib::SourceLocality,
44
+ # RelatonBib::SourceLocalityStack>]
45
+ def initialize(type:, description: nil, bibitem:, locality: [],
46
+ source_locality: [])
47
+ type = "obsoletes" if type == "Now withdrawn"
48
+ unless TYPES.include? type
49
+ warn "[relaton-bib] WARNING: invalid relation type: #{type}"
50
+ end
40
51
  @type = type
52
+ @description = description
41
53
  @locality = locality
42
54
  @source_locality = source_locality
43
55
  @bibitem = bibitem
44
56
  end
45
57
 
58
+ # rubocop:disable Metrics/AbcSize
59
+
46
60
  # @param builder [Nokogiri::XML::Builder]
47
61
  def to_xml(builder, **opts)
48
62
  opts.delete :bibdata
49
63
  opts.delete :note
50
64
  builder.relation(type: type) do
65
+ builder.description { description.to_xml builder } if description
51
66
  bibitem.to_xml(builder, **opts.merge(embedded: true))
52
67
  locality.each { |l| l.to_xml builder }
53
68
  source_locality.each { |l| l.to_xml builder }
54
69
  end
55
70
  end
71
+ # rubocop:enable Metrics/AbcSize
56
72
 
57
73
  # @return [Hash]
58
74
  def to_hash
59
75
  hash = { "type" => type, "bibitem" => bibitem.to_hash }
76
+ hash["description"] = description.to_hash if description
60
77
  hash["locality"] = single_element_array(locality) if locality&.any?
61
78
  if source_locality&.any?
62
79
  hash["source_locality"] = single_element_array(source_locality)
@@ -23,9 +23,12 @@ module RelatonBib
23
23
  @array = relation.map { |r| r.is_a?(Hash) ? DocumentRelation.new(r) : r }
24
24
  end
25
25
 
26
+ # @todo We don't have replace type anymore. Suppose we should update this
27
+ # method or delete it.
28
+ #
26
29
  # @return [RelatonBib::DocRelationCollection]
27
30
  def replaces
28
- DocRelationCollection.new @array.select { |r| r.type == "replace" }
31
+ DocRelationCollection.new(@array.select { |r| r.type == "replace" })
29
32
  end
30
33
  end
31
34
  end
@@ -5,21 +5,21 @@ require "relaton_bib/localized_string"
5
5
  module RelatonBib
6
6
  # Document status.
7
7
  class DocumentStatus
8
- # @return [String]
8
+ # @return [RelatonBib::DocumentStatus::Stage]
9
9
  attr_reader :stage
10
10
 
11
- # @return [String, NilClass]
11
+ # @return [RelatonBib::DocumentStatus::Stage, NilClass]
12
12
  attr_reader :substage
13
13
 
14
14
  # @return [String, NilClass]
15
15
  attr_reader :iteration
16
16
 
17
- # @param stage [String]
18
- # @param substage [String, NilClass]
17
+ # @param stage [String, Hash, RelatonBib::DocumentStatus::Stage]
18
+ # @param substage [String, Hash, NilClass, RelatonBib::DocumentStatus::Stage]
19
19
  # @param iteration [String, NilClass]
20
20
  def initialize(stage:, substage: nil, iteration: nil)
21
- @stage = stage
22
- @substage = substage
21
+ @stage = stage_new stage
22
+ @substage = stage_new substage
23
23
  @iteration = iteration
24
24
  end
25
25
 
@@ -27,18 +27,57 @@ module RelatonBib
27
27
  def to_xml(builder)
28
28
  builder.status do
29
29
  # FormattedString.instance_method(:to_xml).bind(status).call builder
30
- builder.stage stage
31
- builder.substage substage if substage
30
+ builder.stage { |b| stage.to_xml b }
31
+ builder.substage { |b| substage.to_xml b } if substage
32
32
  builder.iteration iteration unless iteration.to_s.empty?
33
33
  end
34
34
  end
35
35
 
36
36
  # @return [Hash]
37
37
  def to_hash
38
- hash = { "stage" => stage }
39
- hash["substage"] = substage if substage
38
+ hash = { "stage" => stage.to_hash }
39
+ hash["substage"] = substage.to_hash if substage
40
40
  hash["iteration"] = iteration if iteration
41
41
  hash
42
42
  end
43
+
44
+ private
45
+
46
+ # @param stg [RelatonBib::DocumentStatus::Stage, Hash, String, NilClass]
47
+ # @return [RelatonBib::DocumentStatus::Stage]
48
+ def stage_new(stg)
49
+ if stg.is_a?(Stage) then stg
50
+ elsif stg.is_a?(Hash) then Stage.new(stg)
51
+ elsif stg.is_a?(String) then Stage.new(value: stg)
52
+ end
53
+ end
54
+
55
+ class Stage
56
+ # @return [String]
57
+ attr_reader :value
58
+
59
+ # @return [String, NilClass]
60
+ attr_reader :abbreviation
61
+
62
+ # @parma value [String]
63
+ # @param abbreviation [String, NilClass]
64
+ def initialize(value:, abbreviation: nil)
65
+ @value = value
66
+ @abbreviation = abbreviation
67
+ end
68
+
69
+ # @param [Nokogiri::XML::Builder]
70
+ def to_xml(builder)
71
+ builder.parent[:abbreviation] = abbreviation if abbreviation
72
+ builder.text value
73
+ end
74
+
75
+ # @return [Hash]
76
+ def to_hash
77
+ hash = { "value" => value }
78
+ hash["abbreviation"] = abbreviation if abbreviation
79
+ hash
80
+ end
81
+ end
43
82
  end
44
83
  end
@@ -12,7 +12,7 @@ module RelatonBib
12
12
  # @return [String]
13
13
  attr_reader :format
14
14
 
15
- # @param content [String]
15
+ # @param content [String, Array<RelatonBib::LocalizedString>]
16
16
  # @param language [String, NilClass] language code Iso639
17
17
  # @param script [String, NilClass] script code Iso15924
18
18
  # @param format [String] the content type
@@ -36,8 +36,8 @@ module RelatonBib
36
36
  hash = super
37
37
  return hash unless format
38
38
 
39
- hash = { "content" => hash } if hash.is_a? String
40
- hash["format"] = format if format
39
+ hash = { "content" => hash } unless hash.is_a? Hash
40
+ hash["format"] = format
41
41
  hash
42
42
  end
43
43
  end
@@ -1,6 +1,11 @@
1
1
  module RelatonBib
2
2
  class HashConverter
3
3
  class << self
4
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
5
+
6
+ # @param args [Hash]
7
+ # @param neated [TrueClas, FalseClass] default true
8
+ # @return [Hash]
4
9
  def hash_to_bib(args, nested = false)
5
10
  return nil unless args.is_a?(Hash)
6
11
 
@@ -18,6 +23,7 @@ module RelatonBib
18
23
  formattedref_hash_to_bib(ret)
19
24
  docstatus_hash_to_bib(ret)
20
25
  contributors_hash_to_bib(ret)
26
+ copyright_hash_to_bib(ret)
21
27
  relations_hash_to_bib(ret)
22
28
  series_hash_to_bib(ret)
23
29
  medium_hash_to_bib(ret)
@@ -30,6 +36,7 @@ module RelatonBib
30
36
  ret[:license] = array(ret[:license])
31
37
  ret
32
38
  end
39
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
33
40
 
34
41
  def timestamp_hash(ret)
35
42
  ret[:fetched] ||= Date.today.to_s
@@ -52,7 +59,8 @@ module RelatonBib
52
59
  ret[:title] = ret[:title].map do |t|
53
60
  if t.is_a?(Hash) then t
54
61
  else
55
- { content: t, language: "en", script: "Latn", format: "text/plain", type: "main" }
62
+ { content: t, language: "en", script: "Latn", format: "text/plain",
63
+ type: "main" }
56
64
  end
57
65
  end
58
66
  end
@@ -151,12 +159,21 @@ module RelatonBib
151
159
 
152
160
  def docstatus_hash_to_bib(ret)
153
161
  ret[:docstatus] && ret[:docstatus] = DocumentStatus.new(
154
- stage: ret[:docstatus][:stage],
155
- substage: ret[:docstatus][:substage],
162
+ stage: stage(ret[:docstatus][:stage]),
163
+ substage: stage(ret[:docstatus][:substage]),
156
164
  iteration: ret[:docstatus][:iteration],
157
165
  )
158
166
  end
159
167
 
168
+ # @param stg [Hash]
169
+ # @return [RelatonBib::DocumentStatus::Stage]
170
+ def stage(stg)
171
+ return unless stg
172
+
173
+ args = stg.is_a?(String) ? { value: stg } : stg
174
+ DocumentStatus::Stage.new(**args)
175
+ end
176
+
160
177
  def contributors_hash_to_bib(ret)
161
178
  return unless ret[:contributor]
162
179
 
@@ -252,12 +269,25 @@ module RelatonBib
252
269
  end
253
270
  end
254
271
 
272
+ # @param ret [Hash]
273
+ def copyright_hash_to_bib(ret)
274
+ return unless ret[:copyright]
275
+
276
+ ret[:copyright] = array(ret[:copyright]).map do |c|
277
+ c[:owner] = array(c[:owner])
278
+ c
279
+ end
280
+ end
281
+
255
282
  # @param ret [Hash]
256
283
  def relations_hash_to_bib(ret)
257
284
  return unless ret[:relation]
258
285
 
259
286
  ret[:relation] = array(ret[:relation])
260
287
  ret[:relation]&.each do |r|
288
+ if r[:description]
289
+ r[:description] = FormattedString.new r[:description]
290
+ end
261
291
  relation_bibitem_hash_to_bib(r)
262
292
  relation_locality_hash_to_bib(r)
263
293
  relation_source_locality_hash_to_bib(r)
@@ -312,7 +342,7 @@ module RelatonBib
312
342
  ret[:series] = array(ret[:series])&.map do |s|
313
343
  s[:formattedref] && s[:formattedref] = formattedref(s[:formattedref])
314
344
  if s[:title]
315
- s[:title] = { content: s[:title] } unless s.is_a?(Hash)
345
+ s[:title] = { content: s[:title] } unless s[:title].is_a?(Hash)
316
346
  s[:title] = typed_title_strig(s[:title])
317
347
  end
318
348
  s[:abbreviation] && s[:abbreviation] = localizedstring(s[:abbreviation])
@@ -343,9 +373,9 @@ module RelatonBib
343
373
  def validity_hash_to_bib(ret)
344
374
  return unless ret[:validity]
345
375
 
346
- ret[:validity][:begins] && b = Time.parse(ret[:validity][:begins])
347
- ret[:validity][:ends] && e = Time.parse(ret[:validity][:ends])
348
- ret[:validity][:revision] && r = Time.parse(ret[:validity][:revision])
376
+ ret[:validity][:begins] && b = Time.parse(ret[:validity][:begins].to_s)
377
+ ret[:validity][:ends] && e = Time.parse(ret[:validity][:ends].to_s)
378
+ ret[:validity][:revision] && r = Time.parse(ret[:validity][:revision].to_s)
349
379
  ret[:validity] = Validity.new(begins: b, ends: e, revision: r)
350
380
  end
351
381
 
@@ -11,21 +11,35 @@ module RelatonBib
11
11
  # @return [Array<String>] script Iso15924 code
12
12
  attr_reader :script
13
13
 
14
- # @return [String]
14
+ # @return [String, Array<RelatonBib::LocalizedString>]
15
15
  attr_accessor :content
16
16
 
17
- # @param content [String]
17
+ # @param content [String, Array<RelatonBib::LocalizedString>]
18
18
  # @param language [String] language code Iso639
19
19
  # @param script [String] script code Iso15924
20
20
  def initialize(content, language = nil, script = nil)
21
+ unless content.is_a?(String) || content.is_a?(Array) &&
22
+ (inv = content.reject { |c| c.is_a?(LocalizedString) || c.is_a?(Hash) }).
23
+ none? && content.any?
24
+ klass = content.is_a?(Array) ? inv.first.class : content.class
25
+ raise ArgumentError, "invalid LocalizedString content type: #{klass}"
26
+ end
21
27
  @language = language.is_a?(String) ? [language] : language
22
28
  @script = script.is_a?(String) ? [script] : script
23
- @content = content
29
+ @content = if content.is_a?(Array)
30
+ content.map do |c|
31
+ if c.is_a?(Hash)
32
+ LocalizedString.new c[:content], c[:language], c[:script]
33
+ else c
34
+ end
35
+ end
36
+ else content
37
+ end
24
38
  end
25
39
 
26
40
  # @return [String]
27
41
  def to_s
28
- content
42
+ content.is_a?(String) ? content : content.first.to_s
29
43
  end
30
44
 
31
45
  # @return [TrueClass, FalseClass]
@@ -37,19 +51,26 @@ module RelatonBib
37
51
  def to_xml(builder)
38
52
  return unless content
39
53
 
40
- builder.parent["language"] = language.join(",") if language&.any?
41
- builder.parent["script"] = script.join(",") if script&.any?
42
- builder.text content.encode(xml: :text)
54
+ if content.is_a?(Array)
55
+ content.each { |c| builder.variant { c.to_xml builder } }
56
+ else
57
+ builder.parent["language"] = language.join(",") if language&.any?
58
+ builder.parent["script"] = script.join(",") if script&.any?
59
+ builder.text content.encode(xml: :text)
60
+ end
43
61
  end
44
62
 
45
63
  # @return [Hash]
46
64
  def to_hash
47
- return content unless language || script
65
+ if content.is_a? String
66
+ return content unless language || script
48
67
 
49
- hash = { "content" => content }
50
- hash["language"] = single_element_array(language) if language&.any?
51
- hash["script"] = single_element_array(script) if script&.any?
52
- hash
68
+ hash = { "content" => content }
69
+ hash["language"] = single_element_array(language) if language&.any?
70
+ hash["script"] = single_element_array(script) if script&.any?
71
+ hash
72
+ else content.map &:to_hash
73
+ end
53
74
  end
54
75
  end
55
76
  end
@@ -1,14 +1,12 @@
1
1
  module RelatonBib
2
2
  class TypedTitleString
3
- # TITLE_TYPES = %w[alternative original unofficial subtitle main].freeze
4
-
5
3
  # @return [String]
6
4
  attr_reader :type
7
5
 
8
6
  # @return [RelatonBib::FormattedString]
9
7
  attr_reader :title
10
8
 
11
- # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
9
+ # rubocop:disable Metrics/MethodLength
12
10
 
13
11
  # @param type [String]
14
12
  # @param title [RelatonBib::FormattedString, Hash]
@@ -16,10 +14,6 @@ module RelatonBib
16
14
  # @param language [String]
17
15
  # @param script [String]
18
16
  def initialize(**args)
19
- # if args[:type] && !TITLE_TYPES.include?(args[:type])
20
- # warn %{[relaton-bib] title type "#{args[:type]}" is invalid.}
21
- # end
22
-
23
17
  unless args[:title] || args[:content]
24
18
  raise ArgumentError, %{Keyword "title" or "content" should be passed.}
25
19
  end
@@ -30,12 +24,12 @@ module RelatonBib
30
24
  @title = args[:title]
31
25
  else
32
26
  fsargs = args.select do |k, _v|
33
- %i[content language script format].include? k
27
+ %i[content language script format].include? k
34
28
  end
35
29
  @title = FormattedString.new(fsargs)
36
30
  end
37
31
  end
38
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
32
+ # rubocop:enable Metrics/MethodLength
39
33
 
40
34
  # @param builder [Nokogiri::XML::Builder]
41
35
  def to_xml(builder)
@@ -1,3 +1,3 @@
1
1
  module RelatonBib
2
- VERSION = "1.0.0".freeze
2
+ VERSION = "1.1.0".freeze
3
3
  end
@@ -91,12 +91,16 @@ module RelatonBib
91
91
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
92
92
 
93
93
  def fetch_series(item)
94
- item.xpath("./series").map do |sr|
94
+ item.xpath("./series").reduce([]) do |mem, sr|
95
95
  abbr = sr.at "abbreviation"
96
96
  abbreviation = abbr ? LocalizedString.new(abbr.text, abbr[:language], abbr[:script]) : nil
97
- Series.new(
98
- type: sr[:type], formattedref: fref(sr),
99
- title: ttitle(sr.at("title")), place: sr.at("place")&.text,
97
+ formattedref = fref(sr)
98
+ title = ttitle(sr.at("title"))
99
+ next mem unless formattedref || title
100
+
101
+ mem << Series.new(
102
+ type: sr[:type], formattedref: formattedref,
103
+ title: title, place: sr.at("place")&.text,
100
104
  organization: sr.at("organization")&.text,
101
105
  abbreviation: abbreviation, from: sr.at("from")&.text,
102
106
  to: sr.at("to")&.text, number: sr.at("number")&.text,
@@ -155,8 +159,12 @@ module RelatonBib
155
159
  def ttitle(title)
156
160
  return unless title
157
161
 
162
+ variants = title.xpath("variant").map do |v|
163
+ LocalizedString.new v.text, v[:language], v[:script]
164
+ end
165
+ content = variants.any? ? variants : title.text
158
166
  TypedTitleString.new(
159
- type: title[:type], content: title.text, language: title[:language],
167
+ type: title[:type], content: content, language: title[:language],
160
168
  script: title[:script], format: title[:format]
161
169
  )
162
170
  end
@@ -165,14 +173,22 @@ module RelatonBib
165
173
  status = item.at("./status")
166
174
  return unless status
167
175
 
168
- stage = status.at "stage"
176
+ stg = status.at "stage"
169
177
  DocumentStatus.new(
170
- stage: stage ? stage.text : status.text,
171
- substage: status.at("substage")&.text,
178
+ stage: stg ? stage(stg) : status.text,
179
+ substage: stage(status.at("substage")),
172
180
  iteration: status.at("iteration")&.text,
173
181
  )
174
182
  end
175
183
 
184
+ # @param node [Nokogiri::XML::Elemen]
185
+ # @return [RelatonBib::DocumentStatus::Stage]
186
+ def stage(elm)
187
+ return unless elm
188
+
189
+ DocumentStatus::Stage.new value: elm.text, abbreviation: elm[:abbreviation]
190
+ end
191
+
176
192
  def fetch_dates(item)
177
193
  item.xpath("./date").reduce([]) do |a, d|
178
194
  type = d[:type].to_s.empty? ? "published" : d[:type]
@@ -228,14 +244,9 @@ module RelatonBib
228
244
  end
229
245
 
230
246
  cn = person.at "./name/completename"
231
- cname = if cn
232
- LocalizedString.new(cn.text, cn[:language], cn[:script])
233
- else
234
- nil
235
- end
236
-
247
+ cname = cn && LocalizedString.new(cn.text, cn[:language], cn[:script])
237
248
  sn = person.at "./name/surname"
238
- sname = sn ? LocalizedString.new(sn.text, sn[:language], sn[:script]) : nil
249
+ sname = sn && LocalizedString.new(sn.text, sn[:language], sn[:script])
239
250
 
240
251
  name = FullName.new(
241
252
  completename: cname, surname: sname,
@@ -275,25 +286,24 @@ module RelatonBib
275
286
  # @return [Array<RelatonBib::FormattedString>]
276
287
  def fetch_abstract(item)
277
288
  item.xpath("./abstract").map do |a|
278
- FormattedString.new(
279
- content: a.text, language: a[:language], script: a[:script], format: a[:format]
280
- )
289
+ FormattedString.new(content: a.text, language: a[:language],
290
+ script: a[:script], format: a[:format])
281
291
  end
282
292
  end
283
293
 
284
294
  # @param item [Nokogiri::XML::Element]
285
- # @return [RelatonBib::CopyrightAssociation]
295
+ # @return [Array<RelatonBib::CopyrightAssociation>]
286
296
  def fetch_copyright(item)
287
- cp = item.at("./copyright") || return
288
- org = cp&.at("owner/organization")
289
- name = org&.at("name")&.text
290
- abbr = org&.at("abbreviation")&.text
291
- url = org&.at("uri")&.text
292
- entity = Organization.new(name: name, abbreviation: abbr, url: url)
293
- from = cp.at("from")&.text
294
- to = cp.at("to")&.text
295
- owner = ContributionInfo.new entity: entity
296
- CopyrightAssociation.new(owner: owner, from: from, to: to)
297
+ item.xpath("./copyright").map do |cp|
298
+ owner = cp.xpath("owner").map do |o|
299
+ ContributionInfo.new entity: get_org(o.at("organization"))
300
+ end
301
+ from = cp.at("from")&.text
302
+ to = cp.at("to")&.text
303
+ scope = cp.at("scope")&.text
304
+ CopyrightAssociation.new(owner: owner, from: from, to: to,
305
+ scope: scope)
306
+ end
297
307
  end
298
308
 
299
309
  # @param item [Nokogiri::XML::Element]
@@ -310,6 +320,7 @@ module RelatonBib
310
320
  item.xpath("./relation").map do |rel|
311
321
  DocumentRelation.new(
312
322
  type: rel[:type]&.empty? ? nil : rel[:type],
323
+ description: relation_description(rel),
313
324
  bibitem: bib_item(item_data(rel.at("./bibitem"))),
314
325
  locality: localities(rel),
315
326
  source_locality: source_localities(rel),
@@ -317,6 +328,16 @@ module RelatonBib
317
328
  end
318
329
  end
319
330
 
331
+ # @param rel [Nokogiri::XML::Element]
332
+ # @return [RelatonBib::FormattedString, NilClass]
333
+ def relation_description(rel)
334
+ d = rel.at "./description"
335
+ return unless d
336
+
337
+ FormattedString.new(content: d.text, language: d[:language],
338
+ script: d[:script], format: d[:format])
339
+ end
340
+
320
341
  # @param item_hash [Hash]
321
342
  # @return [RelatonBib::BibliographicItem]
322
343
  def bib_item(item_hash)
@@ -1,4 +1,4 @@
1
- lib = File.expand_path("../lib", __FILE__)
1
+ lib = File.expand_path("lib", __dir__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
  require "relaton_bib/version"
4
4
 
@@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
15
15
 
16
16
  # Specify which files should be added to the gem when it is released.
17
17
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
18
- spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
18
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
19
19
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
20
  end
21
21
  spec.bindir = "exe"
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.require_paths = ["lib"]
24
24
  spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
25
25
 
26
+ spec.add_development_dependency "byebug"
26
27
  spec.add_development_dependency "debase"
27
28
  spec.add_development_dependency "equivalent-xml", "~> 0.6"
28
29
  spec.add_development_dependency "rake", "~> 10.0"
@@ -30,7 +31,6 @@ Gem::Specification.new do |spec|
30
31
  spec.add_development_dependency "ruby-debug-ide"
31
32
  spec.add_development_dependency "ruby-jing"
32
33
  spec.add_development_dependency "simplecov"
33
- spec.add_development_dependency "byebug"
34
34
 
35
35
  spec.add_dependency "addressable"
36
36
  spec.add_dependency "bibtex-ruby"
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: relaton-bib
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-04-25 00:00:00.000000000 Z
11
+ date: 2020-06-03 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: byebug
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: debase
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -108,20 +122,6 @@ dependencies:
108
122
  - - ">="
109
123
  - !ruby/object:Gem::Version
110
124
  version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: byebug
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: addressable
127
127
  requirement: !ruby/object:Gem::Requirement