Class: Pubid::Iec::UrnParser
- Inherits:
-
Object
- Object
- Pubid::Iec::UrnParser
- Defined in:
- lib/pubid/iec/urn_parser.rb
Overview
Parses RFC 5141-bis compliant URNs into IEC identifiers
URN format: urn:iec:std:publisher:type:number:year:supplements
Examples:
-
urn:iec:std:iec:60050:2011
-
urn:iec:std:iec:tr:60050:2011
-
urn:iec:std:iec:60050-100:2011
-
urn:iec:std:iec:60050:2011:amd:1:2020
Constant Summary collapse
- TYPED_STAGE_REVERSE_MAP =
Reverse mappings from URN format to PubID components
{ "WD" => :wd, "WDS" => :wds, "CD" => :cd, "CDV" => :cdv, "DIS" => :dis, "FDIS" => :fdis, "PDAM" => :pdam, "DAM" => :dam, "FDAM" => :fdamd, "DCOR" => :dcor, "FDCOR" => :fdcor, "CDTS" => :cdts, "DTS" => :dts, "FDTS" => :fdts, "PRF" => :prf, "PWI" => :pwi, "NP" => :np, "AWI" => :awi, "NWIP" => :nwip, }.freeze
- SUPPLEMENT_TYPE_MAP =
{ "amd" => :amd, "cor" => :cor, }.freeze
- TYPE_CODE_REVERSE_MAP =
{ "tr" => :tr, "ts" => :ts, "pas" => :pas, "guide" => :guide, "isp" => :isp, "r" => :r, "sr" => :sr, "tap" => :tap, }.freeze
Class Method Summary collapse
-
.parse(urn) ⇒ Identifier
Parse IEC URN string.
Instance Method Summary collapse
-
#parse_urn(urn) ⇒ Identifier
Parse URN string into identifier.
Class Method Details
.parse(urn) ⇒ Identifier
Parse IEC URN string
57 58 59 |
# File 'lib/pubid/iec/urn_parser.rb', line 57 def self.parse(urn) new.parse_urn(urn) end |
Instance Method Details
#parse_urn(urn) ⇒ Identifier
Parse URN string into identifier
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/pubid/iec/urn_parser.rb', line 64 def parse_urn(urn) # Remove urn:iec:std: prefix unless urn.start_with?("urn:iec:std:") raise Errors::ParseError, "Invalid IEC URN: #{urn}" end parts = urn.sub("urn:iec:std:", "").split(":") # Parse publisher(s) - first part publishers = parse_publisher(parts.shift) # Parse type - optional (defaults to IS) type_code = nil type_code = parse_type(parts.first) if parts.first && TYPE_CODE_REVERSE_MAP.key?(parts.first.downcase) parts.shift if type_code # Parse number number_part = parts.shift number, part, subpart = parse_number_part(number_part) # Check for stage (stage-XX.XX or typed stage like WD, CD, etc.) stage_code = nil stage_iteration = nil if parts.first&.start_with?("stage-") stage_code, stage_iteration = parse_stage_code(parts.shift) elsif TYPED_STAGE_REVERSE_MAP.key?(parts.first&.upcase) stage_abbr = parts.shift.upcase stage_code = TYPED_STAGE_REVERSE_MAP[stage_abbr] # Check for iteration (WD.2 format) if stage_abbr.include?(".") stage_code, stage_iteration = stage_abbr.split(".") stage_code = TYPED_STAGE_REVERSE_MAP[stage_code] stage_iteration = stage_iteration.to_i end end # Parse date if present (year or year-month) date = nil if parts.first&.match(/^\d{4}(-\d{2})?$/) date = parts.shift end # Parse edition if present (ed.N format) edition = nil if parts.first&.start_with?("ed.") edition = parts.shift.sub("ed.", "").to_i end # Check for supplements (amd, cor) supplements = [] while parts.any? supp_type = nil supp_number = nil supp_date = nil supp_stage = nil # Check for supplement stage if parts.first&.start_with?("stage-") supp_stage_data = parts.shift supp_stage, = parse_stage_code(supp_stage_data) elsif TYPED_STAGE_REVERSE_MAP.key?(parts.first&.upcase) supp_stage_abbr = parts.shift.upcase supp_stage = TYPED_STAGE_REVERSE_MAP[supp_stage_abbr] end # Check for supplement type (amd, cor) if SUPPLEMENT_TYPE_MAP.key?(parts.first&.downcase) supp_type = SUPPLEMENT_TYPE_MAP[parts.shift.downcase] end # Check for version (v1, v2, etc.) or number if parts.first&.start_with?("v") version_str = parts.shift supp_number = version_str.sub("v", "").to_i elsif parts.first&.match(/^\d+$/) # Could be year or supplement number if parts.first&.match(/^\d{4}$/) # 4 digits = year supp_date = parts.shift else # 1-3 digits = supplement number supp_number = parts.shift.to_i end end # Next part might be year if not already set if supp_date.nil? && parts.first&.match(/^\d{4}(-\d{2})?$/) supp_date = parts.shift end # Safety: consume unrecognized token to prevent infinite loop unless supp_type || supp_number || supp_date || supp_stage parts.shift end supplements << { type: supp_type, number: supp_number, date: supp_date, stage: supp_stage, } end # Build the identifier hash build_identifier(publishers, number, part, subpart, type_code, stage_code, stage_iteration, date, edition, supplements) end |