relaton-bib 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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