Class: Pubid::Ieee::Identifier
- Inherits:
-
Pubid::Identifier
- Object
- Lutaml::Model::Serializable
- Pubid::Identifier
- Pubid::Ieee::Identifier
- Defined in:
- lib/pubid/ieee/identifiers/base.rb
Overview
Base class for all IEEE identifiers. Canonical name Pubid::Ieee::Identifier. IEEE builds its identifiers as instances of this class directly.
Direct Known Subclasses
Aiee::Identifier, Pubid::Ieee::Identifiers::AdoptedStandard, Pubid::Ieee::Identifiers::CsaDualPublished, Pubid::Ieee::Identifiers::DualIdentifier, Pubid::Ieee::Identifiers::DualPublished, Pubid::Ieee::Identifiers::IecIeeeCopublished, Pubid::Ieee::Identifiers::JointDevelopment, Pubid::Ieee::Identifiers::MultiNumberedIdentifier, Pubid::Ieee::Identifiers::Nesc::Base, Pubid::Ieee::Identifiers::ParentheticalIdentifier, Pubid::Ieee::Identifiers::ProjectDraftIdentifier, Pubid::Ieee::Identifiers::RedlinedStandard, Pubid::Ieee::Identifiers::SiStandard, Pubid::Ieee::Identifiers::Standard, Pubid::Ieee::Identifiers::SupplementIdentifier, Pubid::Ieee::Ire::Identifier
Instance Attribute Summary collapse
-
#code_obj ⇒ Object
Lazily rebuild the parsed component objects from the underlying string attributes.
-
#draft_obj ⇒ Object
Store actual component objects.
Class Method Summary collapse
-
.additional_identifier_classes ⇒ Object
Register the identifier classes the automatic
Identifiers::*scan cannot see, soPubid::Ieee::Identifier.from_hashcan route their rows back. -
.from_hash(data, options = {}) ⇒ Object
Inverse of the to_hash compaction: expand a scalar
stageback into thetyped_stagesub-hash (on a deep copy, recursively) before lutaml deserializes, so nested bases rebuild their component too. -
.parse(input) ⇒ Object
Parse IEEE identifier string.
-
.parse_single(input) ⇒ Object
Parse a single IEEE identifier.
Instance Method Summary collapse
-
#code ⇒ Object
Override accessors to return component objects.
- #draft ⇒ Object
-
#draft_month ⇒ Object
Expose numeric month from draft if available.
-
#exclude(*args) ⇒ Object
IEEE stores its publication date as separate
year/month/day:string attributes, not a Components::Date, so the base #exclude's:year->:dateremap can't reach them (it would nil an unuseddatecomponent and leave the strings). -
#initialize(args = {}, **kwargs) ⇒ Identifier
constructor
Accept either keyword args (
new(number: "802"), the normal path) or a single positional attribute hash (new({number: "802"})). - #mr_number_with_part ⇒ Object
-
#mr_publisher ⇒ Object
IEEE stores identity in
code(prefix/number/parts) rather than the genericnumber, has its owntypestring ("Std", "Draft Std"), and carriesyearas a bare string — none of which the generic MrString renderer knows about. - #mr_type ⇒ Object
- #mr_year ⇒ Object
-
#publisher ⇒ String
Generate URN for this identifier.
-
#to_hash(*args) ⇒ Object
Compact the serialized hash (recursively, so nested Corrigendum bases are compacted too) after the normal serialize + canonicalize: collapse
typed_stageto a scalarstageand strip the/offdraft.
Methods inherited from Pubid::Identifier
apply_mappings, #base, #base_document, concrete_class_for, #dated_version_of?, #draft_of?, #drop_supplements, #edition_of?, #eql?, #has_supplement?, #hash, #includes?, #matches?, #mr_all_parts, #mr_edition, #mr_languages, #mr_number, #mr_part, #mr_subpart, #mr_supplement_suffix, #new_edition_of?, polymorphic_name, polymorphic_type_map, #related_to?, #render, #resolve_urn_generator, #root, #sibling_of?, #supplement_of?, #to_mr_string, #to_s, #to_slug, #to_supplement_s, #to_urn, #urn_supplement_type, #urn_type_code, #year
Constructor Details
#initialize(args = {}, **kwargs) ⇒ Identifier
Accept either keyword args (new(number: "802"), the normal path) or a
single positional attribute hash (new({number: "802"})). The latter is
what the base Pubid::Identifier#exclude/matching machinery uses when it
rebuilds via self.class.new(attrs); without it, exclude/matches?
raised ArgumentError for every IEEE identifier.
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 |
# File 'lib/pubid/ieee/identifiers/base.rb', line 75 def initialize(args = {}, **kwargs) args = args.merge(kwargs) unless kwargs.empty? super() # Handle typed_stage if provided if args[:typed_stage] self.typed_stage = args[:typed_stage] end # Handle code as component object. `code` is runtime-only (not a lutaml # attribute) — we keep the parsed Components::Code in code_obj; every # leaf serializes the split index columns (number/prefix/parts/separator) # via the CodeNumber mixin instead of a `code` string. The renderer reads # code_obj (base #code returns it). if args[:code].is_a?(String) self.code_obj = Components::Code.parse(args[:code]) elsif args[:code] self.code_obj = args[:code] end # Handle draft as component object if args[:draft_obj] self.draft_obj = args[:draft_obj] self.draft = args[:draft_obj].to_s elsif args[:draft].is_a?(String) self.draft_obj = Components::Draft.parse(args[:draft]) self.draft = draft_obj.to_s elsif args[:draft] self.draft_obj = args[:draft] self.draft = args[:draft].to_s end # Set other attributes attrs = self.class.attributes args.each do |key, value| next if %i[code draft draft_obj typed_stage].include?(key) setter = :"#{key}=" public_send(setter, value) if attrs.key?(key) end end |
Instance Attribute Details
#code_obj ⇒ Object
Lazily rebuild the parsed component objects from the underlying string
attributes. After from_hash, lutaml restores the :code/:draft strings
(@code/@draft) but not these objects; the renderer reads code_obj/
draft_obj directly, so rebuild on demand to render a deserialized
identifier identically to the parsed one. On the parse path code_obj/
draft_obj are already set, so the ||= returns them unchanged.
68 69 70 |
# File 'lib/pubid/ieee/identifiers/base.rb', line 68 def code_obj @code_obj end |
#draft_obj ⇒ Object
Store actual component objects
68 69 70 |
# File 'lib/pubid/ieee/identifiers/base.rb', line 68 def draft_obj @draft_obj end |
Class Method Details
.additional_identifier_classes ⇒ Object
Register the identifier classes the automatic Identifiers::* scan
cannot see, so Pubid::Ieee::Identifier.from_hash can route their rows
back. The scan only looks at classes declared directly under
Identifiers, which misses both AIEE and IRE (they live under their own
Aiee/Ire namespaces) and the whole NESC family (nested one level
deeper, under Identifiers::Nesc).
193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/pubid/ieee/identifiers/base.rb', line 193 def self.additional_identifier_classes [ Aiee::Identifier, Ire::Identifier, Identifiers::Nesc::Draft, Identifiers::Nesc::Edition, Identifiers::Nesc::Handbook, Identifiers::Nesc::Redline, Identifiers::Nesc::Standard, ] end |
.from_hash(data, options = {}) ⇒ Object
Inverse of the to_hash compaction: expand a scalar stage back into the
typed_stage sub-hash (on a deep copy, recursively) before lutaml
deserializes, so nested bases rebuild their component too. draft needs
no expansion (Draft.parse accepts the slashless form).
182 183 184 185 |
# File 'lib/pubid/ieee/identifiers/base.rb', line 182 def self.from_hash(data, = {}) data = Compaction.(Compaction.deep_dup(data)) if data.is_a?(::Hash) super end |
.parse(input) ⇒ Object
Parse IEEE identifier string.
PreParser owns all regex/dispatch logic; this method is a thin orchestrator that consumes a PreParser::Result and routes to the correct builder.
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/pubid/ieee/identifiers/base.rb', line 210 def self.parse(input) if input.length > Pubid::MAX_INPUT_LENGTH raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE end result = PreParser.preprocess(input) case result.dispatch when :aiee_simple return Aiee::Identifier.parse(result.input) when :iec_ieee_copublished return parse_single(result.input) when :dual_semicolon return build_dual(result.parts) when :dual_reaffirmed return build_reaffirmed(result) when :dual_ire return build_dual_with_reaffirmed(result) when :dual_space_separated return build_dual(result.parts) when :dual_and return build_dual(result.parts) when :dual_ampersand return build_dual(result.parts) when :aiee_asa_adoption return build_aiee_asa_adoption(result.parts) when :adopted return build_adopted(result.parts) else parse_single(result.input) end rescue Parslet::ParseFailed parse_single(input) end |
.parse_single(input) ⇒ Object
Parse a single IEEE identifier
314 315 316 317 318 319 320 321 322 |
# File 'lib/pubid/ieee/identifiers/base.rb', line 314 def self.parse_single(input) # Apply legacy update_codes normalization first, before Parser's extensive preprocessing normalized = Core::UpdateCodes.apply(input, :ieee) parsed = Parser.parse(normalized) # Use class method for preprocessing builder = Builder.new(Identifier) # Pass the original input string to builder for context builder.original_input = input builder.build(parsed) end |
Instance Method Details
#code ⇒ Object
Override accessors to return component objects.
118 119 120 |
# File 'lib/pubid/ieee/identifiers/base.rb', line 118 def code code_obj end |
#draft ⇒ Object
122 123 124 |
# File 'lib/pubid/ieee/identifiers/base.rb', line 122 def draft draft_obj end |
#draft_month ⇒ Object
Expose numeric month from draft if available
143 144 145 146 147 |
# File 'lib/pubid/ieee/identifiers/base.rb', line 143 def draft_month return nil unless draft_obj.is_a?(Components::Draft) draft_obj.numeric_month end |
#exclude(*args) ⇒ Object
IEEE stores its publication date as separate year/month/day
:string attributes, not a Components::Date, so the base #exclude's
:year->:date remap can't reach them (it would nil an unused date
component and leave the strings). After the base rebuild, nil the whole
date cluster when :year/:date is excluded, so a date-less reference
matches every date in the bucket (relaton partial-ref matching). NB: the
base #exclude also previously raised for every IEEE id (positional
self.class.new(attrs) vs the keyword initialize) — fixed by
Identifier#initialize accepting a positional hash.
158 159 160 161 162 163 164 165 166 |
# File 'lib/pubid/ieee/identifiers/base.rb', line 158 def exclude(*args) result = super if args.intersect?(%i[year date]) %i[year month day].each do |attr| result.public_send("#{attr}=", nil) if result.respond_to?("#{attr}=") end end result end |
#mr_number_with_part ⇒ Object
339 340 341 |
# File 'lib/pubid/ieee/identifiers/base.rb', line 339 def mr_number_with_part code_obj&.to_s&.downcase end |
#mr_publisher ⇒ Object
IEEE stores identity in code (prefix/number/parts) rather than the
generic number, has its own type string ("Std", "Draft Std"), and
carries year as a bare string — none of which the generic MrString
renderer knows about. Override the lossless MR template directly so
every IEEE identifier round-trips (issue #142). Supplements append
_{type}.{number}.{year} recursively via mr_supplement_suffix.
Lowercased to match the all-lowercase MR convention.
331 332 333 |
# File 'lib/pubid/ieee/identifiers/base.rb', line 331 def mr_publisher publisher&.to_s&.downcase end |
#mr_type ⇒ Object
335 336 337 |
# File 'lib/pubid/ieee/identifiers/base.rb', line 335 def mr_type type&.downcase end |
#mr_year ⇒ Object
343 344 345 |
# File 'lib/pubid/ieee/identifiers/base.rb', line 343 def mr_year year&.to_s end |
#publisher ⇒ String
Generate URN for this identifier
17 |
# File 'lib/pubid/ieee/identifiers/base.rb', line 17 attribute :publisher, :string, default: -> { "IEEE" } |
#to_hash(*args) ⇒ Object
Compact the serialized hash (recursively, so nested Corrigendum bases
are compacted too) after the normal serialize + canonicalize: collapse
typed_stage to a scalar stage and strip the / off draft. See
Compaction for why this is a hash transform, not lutaml attributes.
172 173 174 175 176 |
# File 'lib/pubid/ieee/identifiers/base.rb', line 172 def to_hash(*args) hash = super Compaction.collapse(hash) if hash.is_a?(::Hash) hash end |