pubid-iso 0.2.1 → 0.3.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.
@@ -1,60 +1,115 @@
1
1
  module Pubid::Iso::Renderer
2
2
  class Base < Pubid::Core::Renderer::Base
3
+ attr_accessor :prerendered_params
4
+
5
+ TYPE_VALUES = {
6
+ tr: "TR",
7
+ ts: "TS",
8
+ isp: "ISP",
9
+ guide: "Guide",
10
+ pas: "PAS",
11
+ dpas: "DPAS",
12
+ }.freeze
13
+
14
+ # Prerender parameters
15
+ def prerender(with_edition: true, **args)
16
+ @params[:type_stage] = @params.slice(:stage, :type) if @params[:stage] || @params[:type]
17
+ super
18
+ end
19
+
20
+ def render_supplement(supplement_params, **args)
21
+ if supplement_params[:base].type == :amd
22
+ # render inner amendment (cor -> amd -> base)
23
+ render_supplement(supplement_params[:base].get_params, **args)
24
+ else
25
+ self.class.new(supplement_params[:base].get_params).render_base_identifier(
26
+ # always render year for identifiers with supplement
27
+ **args.merge({ with_date: true }),
28
+ )
29
+ end +
30
+ case supplement_params[:typed_stage].type.type
31
+ when :amd
32
+ render_amendments(
33
+ [Pubid::Iso::Amendment.new(**supplement_params.slice(:number, :year, :typed_stage, :edition, :iteration))],
34
+ args,
35
+ nil,
36
+ )
37
+ when :cor
38
+ render_corrigendums(
39
+ [Pubid::Iso::Corrigendum.new(**supplement_params.slice(:number, :year, :typed_stage, :edition, :iteration))],
40
+ args,
41
+ nil,
42
+ )
43
+ # copy parameters from Identifier only supported by Corrigendum
44
+ end +
45
+ (supplement_params[:base].language ? render_language(supplement_params[:base].language, args, nil) : "")
46
+ end
47
+
3
48
  # Render identifier
4
49
  # @param with_edition [Boolean] include edition in output
5
50
  # @see Pubid::Core::Renderer::Base for another options
6
- def render(with_edition: true, **args)
7
- params = prerender_params(@params,
8
- { with_edition: with_edition }.merge(args))
9
- # render empty string when the key is not exist
10
- params.default = ""
51
+ def render(with_edition: true, with_language_code: :iso, with_date: true, **args)
52
+ # super(**args.merge({ with_edition: with_edition }))
53
+ if %i(amd cor).include? @params[:typed_stage]&.type&.type
54
+ render_supplement(@params, **args.merge({ with_date: with_date,
55
+ with_language_code: with_language_code,
56
+ with_edition: with_edition }))
57
+ else
58
+ render_base_identifier(**args.merge({ with_date: with_date,
59
+ with_language_code: with_language_code,
60
+ with_edition: with_edition })) +
61
+ @prerendered_params[:language].to_s
62
+ end
11
63
 
12
- render_identifier(params)
13
64
  end
14
65
 
15
66
  def render_identifier(params)
16
- if @params[:type] && @params[:stage]
17
- if %w(DIS FDIS).include?(@params[:stage].abbr)
18
- render_base(params, "#{render_short_stage(@params[:stage].abbr)}#{@params[:type]}")
19
- else
20
- if params[:copublisher] && !params[:copublisher].empty?
21
- render_base(params, "%{type}%{stage}" % params)
22
- else
23
- render_base(params, "%{stage}%{type}" % params)
24
- end
25
- end
26
- else
27
- render_base(params, "%{type}%{stage}" % params)
28
- end +
29
- "%{part}%{iteration}%{year}%{amendments}%{corrigendums}%{edition}%{language}" % params
67
+ # typed_stage = if params[:typed_stage] && params[:typed_stage] != ""
68
+ # ((params[:copublisher] && !params[:copublisher].empty?) ? " " : "/") + params[:typed_stage].to_s
69
+ # else
70
+ # ""
71
+ # end
72
+ render_base(params, params[:typed_stage]) +
73
+ ("%{part}%{iteration}%{year}%{amendments}%{corrigendums}%{edition}" % params)
30
74
  end
31
75
 
32
- def render_short_stage(stage)
33
- (params[:copublisher] ? " " : "/") +
34
- case stage
35
- when "DIS"
36
- "D"
37
- when "FDIS"
38
- "FD"
39
- end
76
+ def render_typed_stage(typed_stage, _opts, params)
77
+ (params[:copublisher] ? " " : "/") + typed_stage.to_s
40
78
  end
41
79
 
42
- def render_type(type, opts, params)
43
- if params[:copublisher] || (params[:stage] && params[:stage].abbr != "IS")
44
- " #{type}"
45
- else
46
- "/#{type}"
80
+ # def render_type_stage(values, opts, params)
81
+ #
82
+ # # prerender stage and type before
83
+ # stage = render_stage(values[:stage], opts, params)
84
+ # type = values[:type]&.to_s
85
+ # return unless type || stage
86
+ #
87
+ # if type && stage
88
+ # # don't add prefix for pdf format
89
+ # if %w(DIS FDIS).include?(stage)
90
+ # "#{render_short_stage(stage)}#{type}"
91
+ # else
92
+ # "#{stage} #{type}"
93
+ # end
94
+ # else
95
+ # # when only type or stage
96
+ # "#{type}#{stage}"
97
+ # end
98
+ # end
99
+
100
+ def render_short_stage(stage)
101
+ case stage
102
+ when "DIS"
103
+ "D"
104
+ when "FDIS"
105
+ "FD"
47
106
  end
48
107
  end
49
108
 
50
- def render_stage(stage, opts, params)
51
- return if (stage.abbr == "PRF" and !opts[:with_prf]) || stage.abbr == "IS"
109
+ def render_stage(stage, opts, _params)
110
+ return if stage.nil? || (stage.abbr == "PRF" and !opts[:with_prf]) || stage.abbr == "IS"
52
111
 
53
- if params[:copublisher]
54
- " #{stage.abbr}"
55
- else
56
- "/#{stage.abbr}"
57
- end
112
+ stage.abbr
58
113
  end
59
114
 
60
115
  def render_edition(edition, opts, _params)
@@ -2,7 +2,7 @@ module Pubid::Iso::Renderer
2
2
  class Dir < Base
3
3
 
4
4
  def render_identifier(params)
5
- res = ("%{publisher}%{copublisher} DIR%{dirtype}%{number}%{year}%{supplement}%{language}" % params)
5
+ res = ("%{publisher}%{copublisher} DIR%{dirtype}%{number}%{year}%{supplement}" % params)
6
6
 
7
7
  if params.key?(:joint_document)
8
8
  joint_params = prerender_params(params[:joint_document].get_params, {})
@@ -1,8 +1,13 @@
1
1
  module Pubid::Iso::Renderer
2
2
  class French < Base
3
+ def render_typed_stage(typed_stage, opts, params)
4
+ return nil if typed_stage.type == :guide
5
+
6
+ super
7
+ end
8
+
3
9
  def render_identifier(params)
4
- if params[:type] == " Guide"
5
- params[:type] = ""
10
+ if @params[:typed_stage]&.type == :guide
6
11
  "Guide #{super(params)}"
7
12
  else
8
13
  super
@@ -18,9 +18,16 @@ module Pubid::Iso::Renderer
18
18
  "ISP" => "ИСП",
19
19
  }.freeze
20
20
 
21
+ def render_typed_stage(typed_stage, opts, params)
22
+ return nil if typed_stage.type == :guide
23
+
24
+ return (params[:copublisher] ? " " : "/") + STAGE[typed_stage.to_s] if STAGE.key?(typed_stage.to_s)
25
+
26
+ super
27
+ end
28
+
21
29
  def render_identifier(params)
22
- if params[:type] == " Guide"
23
- params[:type] = ""
30
+ if @params[:typed_stage]&.type == :guide
24
31
  "Руководство #{super(params)}"
25
32
  else
26
33
  super
@@ -43,11 +50,7 @@ module Pubid::Iso::Renderer
43
50
  end
44
51
 
45
52
  def render_stage(stage, _opts, params)
46
- if params[:copublisher]
47
- " #{STAGE[stage.abbr]}"
48
- else
49
- "/#{STAGE[stage.abbr]}"
50
- end
53
+ STAGE[stage.abbr] unless stage.nil?
51
54
  end
52
55
 
53
56
  def render_corrigendums(corrigendums, _opts, _params)
@@ -10,13 +10,42 @@ module Pubid::Iso::Renderer
10
10
  PRF: 50,
11
11
  IS: 60 }.freeze
12
12
 
13
+ def prerender(with_edition: true, **args)
14
+ @params[:type_stage] = @params.slice(:stage, :type) if @params[:stage] || @params[:type]
15
+ super
16
+ end
17
+
18
+ # Render identifier
19
+ # @param with_edition [Boolean] include edition in output
20
+ # @see Pubid::Core::Renderer::Base for another options
21
+ def render(with_edition: true, **args)
22
+ # copy type from typed stage
23
+ @params[:type] = @params[:typed_stage].type if @params[:typed_stage] && @params[:typed_stage].type
24
+ super(**args.merge({ with_edition: with_edition }))
25
+ end
26
+
13
27
  def render_identifier(params)
14
- render_base(params) + "%{stage}"\
15
- "%{corrigendum_stage}%{iteration}%{edition}%{amendments}%{corrigendums}%{language}" % params
28
+ render_base(params) + "%{typed_stage}"\
29
+ "%{corrigendum_stage}%{iteration}%{edition}%{amendments}%{corrigendums}" % params
30
+ end
31
+
32
+ def render_typed_stage(typed_stage, _opts, _params)
33
+ ":stage-#{typed_stage.stage.harmonized_code}" if typed_stage.stage
34
+ end
35
+ # def render_stage(stage, _opts, params)
36
+ # ":stage-#{stage.harmonized_code}"
37
+ # end
38
+
39
+ def render_iteration(iteration, _opts, params)
40
+ ".v#{iteration}" if params[:typed_stage]&.stage
41
+ end
42
+
43
+ def render_type(type, _, _)
44
+ ":#{type.to_s.downcase}" unless type == :is
16
45
  end
17
46
 
18
- def render_stage(stage, _opts, params)
19
- ":stage-#{stage.harmonized_code}"
47
+ def render_year(year, _opts, _params)
48
+ ":#{year}"
20
49
  end
21
50
  end
22
51
  end
@@ -2,17 +2,22 @@ module Pubid::Iso
2
2
  class Stage
3
3
  attr_accessor :abbr, :harmonized_code
4
4
 
5
- STAGES = { PWI: "00.00",
6
- NP: "10.00",
5
+ STAGES = { PWI: %w[00.00 00.20 00.60 00.98 00.99],
6
+ NP: %w[10.00 10.20 10.60 10.98 10.92],
7
7
  AWI: %w[20.00 10.99],
8
8
  WD: %w[20.20 20.60 20.98 20.99],
9
- CD: "30.00",
10
- DIS: "40.00",
11
- FDIS: "50.00",
12
- PRF: "60.00",
13
- IS: "60.60" }.freeze
9
+ CD: %w[30.00 30.20 30.60 30.92 30.98 30.99],
10
+ PRF: "60.00" }.freeze
14
11
 
15
12
 
13
+ STAGE_NAMES = {
14
+ WD: "Working Draft",
15
+ PWI: "Preliminary Work Item",
16
+ NP: "New Proposal",
17
+ CD: "Committee Draft",
18
+ PRF: "Proof of a new International Standard",
19
+ }.freeze
20
+
16
21
  # @param abbr [String, Symbol] abbreviation eg. :PWI, :WD
17
22
  # @param harmonized_code [String, Float, HarmonizedStageCode]
18
23
  def initialize(abbr: nil, harmonized_code: nil)
@@ -22,27 +27,38 @@ module Pubid::Iso
22
27
  @harmonized_code = if harmonized_code.is_a?(HarmonizedStageCode)
23
28
  harmonized_code
24
29
  else
25
- HarmonizedStageCode.new(*harmonized_code.to_s.split("."))
30
+ HarmonizedStageCode.new(harmonized_code)
26
31
  end
27
- @abbr ||= lookup_abbr(@harmonized_code.to_s) || lookup_abbr("#{@harmonized_code.stage}.00")
32
+ @abbr ||= lookup_abbr(@harmonized_code.stages)
33
+ # unless @harmonized_code.fuzzy?
34
+ # @abbr ||= lookup_abbr(@harmonized_code.to_s) || lookup_abbr("#{@harmonized_code.stage}.00")
35
+ # end
28
36
  end
29
37
 
30
38
  if abbr
31
39
  raise Errors::StageInvalidError, "#{abbr} is not valid stage" unless STAGES.key?(abbr.to_sym)
32
40
 
33
- @harmonized_code ||= HarmonizedStageCode.new(*lookup_code(abbr).split("."))
41
+ @harmonized_code ||= HarmonizedStageCode.new(lookup_code(abbr))
34
42
  end
35
43
  end
36
44
 
37
45
  # Lookup for abbreviated code by numeric stage code
38
- # @param lookup_code [String] stage code, e.g. "00.00", "20.20"
46
+ # @param lookup_code [String, Array] stage code or array of stage codes,
47
+ # e.g. "00.00", "20.20", ["00.00", "00.20"]
39
48
  def lookup_abbr(lookup_code)
49
+ lookup_code = lookup_code.first if lookup_code.is_a?(Array) && lookup_code.count == 1
50
+
40
51
  STAGES.each do |abbr, codes|
41
52
  case codes
42
53
  when Array
43
- codes.each do |code|
44
- return abbr if code == lookup_code
54
+ if lookup_code.is_a?(Array)
55
+ return abbr if codes == lookup_code
56
+ else
57
+ return abbr if codes.include?(lookup_code)
45
58
  end
59
+ # codes.each do |code|
60
+ # return abbr if code == lookup_code
61
+ # end
46
62
  when lookup_code
47
63
  return abbr
48
64
  end
@@ -52,8 +68,8 @@ module Pubid::Iso
52
68
  end
53
69
 
54
70
  def lookup_code(lookup_abbr)
55
- code = STAGES[lookup_abbr.to_sym]
56
- code.is_a?(Array) ? code.first : code
71
+ STAGES[lookup_abbr.to_sym]
72
+ # code.is_a?(Array) ? code.first : code
57
73
  end
58
74
 
59
75
  def self.parse(stage)
@@ -66,9 +82,22 @@ module Pubid::Iso
66
82
  end
67
83
  end
68
84
 
85
+ def self.has_stage?(stage)
86
+ if stage.is_a?(Stage)
87
+ STAGES.key?(stage.abbr.to_sym)
88
+ else
89
+ STAGES.key?(stage.to_sym) || /\A[\d.]+\z/.match?(stage)
90
+ end
91
+ end
92
+
69
93
  # Compares one stage with another
70
94
  def ==(other)
71
95
  other&.harmonized_code == harmonized_code
72
96
  end
97
+
98
+ # Return stage name, eg. "Draft International Standard" for "DIS"
99
+ def name
100
+ STAGE_NAMES[abbr.to_sym]
101
+ end
73
102
  end
74
103
  end
@@ -1,34 +1,36 @@
1
1
  module Pubid::Iso
2
2
  class Supplement < Pubid::Core::Supplement
3
- attr_accessor :stage, :publisher, :edition, :iteration
3
+ attr_accessor :typed_stage, :publisher, :edition, :iteration
4
4
 
5
5
  # @param stage [Stage, Symbol, String] stage, e.g. "PWI", "NP", "50.00", Stage.new(abbr: :WD)
6
- # @param publisher [String] publisher, e.g. "ISO", "IEC"
6
+ # @param publisher [String] publisher, e.g. "ISO", "IEC" (only for DIR documents)
7
7
  # @param edition [Integer] edition, e.g. 1, 2, 3
8
8
  # @param iteration [Integer] iteration, e.g. 1, 2, 3
9
9
  # @see Pubid::Core::Supplement for other options
10
- def initialize(stage: nil, publisher: nil, edition: nil, iteration: nil, **args)
10
+ def initialize(typed_stage: nil, publisher: nil, edition: nil, iteration: nil, **args)
11
11
  super(**args)
12
- @stage = stage.is_a?(Stage) ? stage : Stage.parse(stage) if stage
12
+ @typed_stage = TypedStage.parse(typed_stage) if typed_stage
13
+ # for DIR identifiers only
13
14
  @publisher = publisher.to_s
14
15
  @edition = edition&.to_i
15
16
  @iteration = iteration&.to_i
16
17
 
17
- if @iteration && @stage.nil?
18
+ if @iteration && @typed_stage.nil?
18
19
  raise Errors::PublishedIterationError.new("cannot assign iteration to published supplement")
19
20
  end
20
21
  end
21
22
 
22
23
  def render_pubid_stage
23
- ((@stage && @stage.abbr != "IS" && @stage.abbr) || "")
24
+ # @typed_stage.stage.abbr != "IS" &&
25
+ ((@typed_stage && @typed_stage.to_s) || "")
24
26
  end
25
27
 
26
28
  def render_urn_stage
27
- ((@stage && ":stage-#{@stage.harmonized_code}") || "")
29
+ ((@typed_stage&.stage && ":stage-#{@typed_stage.stage.harmonized_code}") || "")
28
30
  end
29
31
 
30
32
  def <=>(other)
31
- (super == 0) && ((stage.nil? || stage == other.stage) && 0 || -1) || super
33
+ (super == 0) && ((typed_stage.nil? || typed_stage == other.typed_stage) && 0 || -1) || super
32
34
  end
33
35
 
34
36
  def render_iteration
@@ -8,13 +8,47 @@ module Pubid::Iso
8
8
  { stage: convert_stage(context[:stage]) }
9
9
  end
10
10
 
11
+ rule(supplements: subtree(:supplements)) do |context|
12
+ context[:supplements] =
13
+ context[:supplements].map do |supplement|
14
+ supplement[:typed_stage] = case supplement[:typed_stage]
15
+ when "PDAM"
16
+ "CD Amd"
17
+ when "pDCOR"
18
+ "CD Cor"
19
+ when "FCOR"
20
+ "FDCor"
21
+ when "FPDAM"
22
+ "DAmd"
23
+ when "FDAM"
24
+ "FDAmd"
25
+ else
26
+ supplement[:typed_stage]
27
+ end
28
+ # Supplement.new(
29
+ # number: supplement[:number],
30
+ # year: supplement[:year],
31
+ # typed_stage:
32
+ # case supplement[:typed_stage]
33
+ # when "FCOR"
34
+ # "FDCor"
35
+ # else
36
+ # supplement[:typed_stage]
37
+ # end,
38
+ # iteration: supplement[:iteration]
39
+ # )
40
+ supplement
41
+ end
42
+ context
43
+ end
44
+
11
45
  rule(amendments: subtree(:amendments)) do |context|
12
46
  context[:amendments] =
13
47
  context[:amendments].map do |amendment|
14
48
  Amendment.new(
15
49
  number: amendment[:number],
16
50
  year: amendment[:year],
17
- stage: amendment[:stage] && convert_stage(amendment[:stage]),
51
+ typed_stage: amendment[:stage] && convert_stage(amendment[:stage]),
18
52
  iteration: amendment[:iteration])
19
53
  end
20
54
  context
@@ -26,7 +60,7 @@ module Pubid::Iso
26
60
  Corrigendum.new(
27
61
  number: corrigendum[:number],
28
62
  year: corrigendum[:year],
29
- stage: corrigendum[:stage] && convert_stage(corrigendum[:stage]),
63
+ typed_stage: corrigendum[:stage] && convert_stage(corrigendum[:stage]),
30
64
  iteration: corrigendum[:iteration])
31
65
  end
32
66
  context
@@ -44,21 +78,26 @@ module Pubid::Iso
44
78
 
45
79
  rule(type: simple(:type)) do
46
80
  russian_type = Renderer::Russian::TYPE.key(type.to_s)
47
- { type: russian_type&.to_s ||
48
- case type
49
- # XXX: can't put 2 alternative Russian translations to dictionary, temporary hack
50
- when "GUIDE", "Руководства"
51
- "Guide"
52
- when "ТС"
53
- "TS"
54
- when "ТО"
55
- "TR"
56
- when "Directives Part", "Directives, Part", "Directives,"
57
- "DIR"
58
- else
59
- type
60
- end
61
- }
81
+ { type: Type.new(russian_type&.downcase&.to_sym ||
82
+ case type
83
+ # XXX: can't put 2 alternative Russian translations to dictionary, temporary hack
84
+ when "GUIDE", "Guide", "Руководства"
85
+ :guide
86
+ when "ТС", "TS"
87
+ :ts
88
+ when "ТО", "TR"
89
+ :tr
90
+ when "Directives Part", "Directives, Part", "Directives,"
91
+ :dir
92
+ when "PAS"
93
+ :pas
94
+ when "DPAS"
95
+ :dpas
96
+ when "DIR"
97
+ :dir
98
+ else
99
+ type
100
+ end) }
62
101
  end
63
102
 
64
103
  rule(copublisher: simple(:copublisher)) do
@@ -119,12 +158,17 @@ module Pubid::Iso
119
158
  "FDIS"
120
159
  when "Fpr"
121
160
  "PRF"
122
- when "pD", "PD"
123
- "CD"
161
+ # when "pD", "PD"
162
+ # "CD"
163
+ when "PDTR"
164
+ "CD TR"
165
+ when "PDTS"
166
+ "CD TS"
124
167
  else
125
168
  code
126
169
  end
127
- Stage.new(abbr: (russian_code || code))
170
+ russian_code || code
171
+ # Stage.new(abbr: (russian_code || code))
128
172
  end
129
173
 
130
174
  def self.convert_language(code)
@@ -0,0 +1,77 @@
1
+ module Pubid::Iso
2
+ class Type
3
+ attr_accessor :type
4
+
5
+ TYPE_NAMES = {
6
+ tr: {
7
+ long: "Technical Report",
8
+ short: "TR",
9
+ },
10
+ ts: {
11
+ long: "Technical Specification",
12
+ short: "TS",
13
+ },
14
+ is: {
15
+ long: "International Standard",
16
+ short: "IS",
17
+ },
18
+ pas: {
19
+ long: "Publicly Available Specification",
20
+ short: "PAS",
21
+ },
22
+ isp: {
23
+ long: "International Standardized Profiles",
24
+ short: "ISP",
25
+ },
26
+ guide: {
27
+ long: "Guide",
28
+ short: "Guide",
29
+ },
30
+ dir: {
31
+ long: "Directives",
32
+ short: "DIR",
33
+ },
34
+ dpas: {
35
+ long: "Publicly Available Specification Draft",
36
+ short: "DPAS",
37
+ },
38
+ cor: {
39
+ short: "Cor",
40
+ },
41
+ amd: {
42
+ short: "Amd",
43
+ },
44
+ }.freeze
45
+
46
+ # Create new type
47
+ # @param type [Symbol]
48
+ def initialize(type)
49
+ raise Errors::WrongTypeError, "#{type} type is not available" unless TYPE_NAMES.key?(type)
50
+
51
+ @type = type
52
+ end
53
+
54
+ def self.parse(type_string)
55
+ TYPE_NAMES.each do |type, values|
56
+ return new(type) if values[:short] == type_string
57
+ end
58
+ raise Errors::ParseTypeError, "Cannot parse '#{type_string}' type"
59
+ end
60
+
61
+ def to_s(format = :short)
62
+ TYPE_NAMES[type][format]
63
+ end
64
+
65
+ def ==(other)
66
+ return type == other if other.is_a?(Symbol)
67
+
68
+ type == other.type
69
+ end
70
+
71
+ def self.has_type?(type)
72
+ TYPE_NAMES.any? do |_, v|
73
+ v[:short] == type
74
+ end
75
+ end
76
+ end
77
+ end