pubid 2.0.0.pre.alpha.2 → 2.0.0.pre.alpha.4
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 +4 -4
- data/README.adoc +5 -1
- data/data/nist/update_codes.yaml +25 -0
- data/lib/pubid/amca/builder.rb +2 -2
- data/lib/pubid/amca/identifier.rb +4 -55
- data/lib/pubid/amca/identifiers/base.rb +58 -47
- data/lib/pubid/amca/identifiers/interpretation.rb +0 -21
- data/lib/pubid/amca/identifiers/publication.rb +0 -17
- data/lib/pubid/amca/identifiers/standard.rb +0 -4
- data/lib/pubid/amca/renderer.rb +82 -0
- data/lib/pubid/amca/single_identifier.rb +0 -23
- data/lib/pubid/amca/urn_generator.rb +2 -1
- data/lib/pubid/amca/urn_parser.rb +28 -0
- data/lib/pubid/amca.rb +42 -1
- data/lib/pubid/ansi/builder.rb +5 -3
- data/lib/pubid/ansi/identifier.rb +1 -43
- data/lib/pubid/ansi/identifiers/american_national_standard.rb +2 -1
- data/lib/pubid/ansi/identifiers/standard.rb +2 -3
- data/lib/pubid/ansi/renderer.rb +53 -0
- data/lib/pubid/ansi/single_identifier.rb +2 -31
- data/lib/pubid/ansi/urn_generator.rb +3 -38
- data/lib/pubid/ansi/urn_parser.rb +23 -0
- data/lib/pubid/ansi.rb +38 -3
- data/lib/pubid/api/builder.rb +33 -74
- data/lib/pubid/api/identifier.rb +5 -52
- data/lib/pubid/api/identifiers/base.rb +2 -14
- data/lib/pubid/api/identifiers/bulletin.rb +0 -2
- data/lib/pubid/api/identifiers/continuous_operations_standard.rb +0 -2
- data/lib/pubid/api/identifiers/mpms.rb +0 -20
- data/lib/pubid/api/identifiers/publication.rb +0 -2
- data/lib/pubid/api/identifiers/recommended_practice.rb +0 -2
- data/lib/pubid/api/identifiers/specification.rb +0 -2
- data/lib/pubid/api/identifiers/standard.rb +0 -2
- data/lib/pubid/api/identifiers/technical_report.rb +0 -2
- data/lib/pubid/api/identifiers/typeless_standard.rb +0 -16
- data/lib/pubid/api/identifiers.rb +18 -0
- data/lib/pubid/api/renderer.rb +89 -0
- data/lib/pubid/api/single_identifier.rb +5 -20
- data/lib/pubid/api/urn_generator.rb +0 -18
- data/lib/pubid/api/urn_parser.rb +35 -0
- data/lib/pubid/api.rb +51 -5
- data/lib/pubid/ashrae/builder.rb +3 -3
- data/lib/pubid/ashrae/identifier.rb +7 -55
- data/lib/pubid/ashrae/identifiers/addenda_package.rb +0 -10
- data/lib/pubid/ashrae/identifiers/addendum.rb +0 -19
- data/lib/pubid/ashrae/identifiers/base.rb +29 -15
- data/lib/pubid/ashrae/identifiers/combined_addenda.rb +0 -15
- data/lib/pubid/ashrae/identifiers/errata.rb +0 -10
- data/lib/pubid/ashrae/identifiers/interpretation.rb +0 -10
- data/lib/pubid/ashrae/parser.rb +4 -0
- data/lib/pubid/ashrae/renderer.rb +117 -0
- data/lib/pubid/ashrae/single_identifier.rb +0 -13
- data/lib/pubid/ashrae/urn_generator.rb +0 -8
- data/lib/pubid/ashrae/urn_parser.rb +27 -0
- data/lib/pubid/ashrae.rb +46 -1
- data/lib/pubid/asme/components/code.rb +10 -2
- data/lib/pubid/asme/identifier.rb +0 -46
- data/lib/pubid/asme/identifiers/base.rb +0 -60
- data/lib/pubid/asme/renderer.rb +66 -0
- data/lib/pubid/asme/single_identifier.rb +3 -1
- data/lib/pubid/asme/urn_parser.rb +31 -0
- data/lib/pubid/asme.rb +42 -1
- data/lib/pubid/astm/components/code.rb +9 -0
- data/lib/pubid/{jis → astm}/components.rb +1 -1
- data/lib/pubid/astm/identifier.rb +0 -77
- data/lib/pubid/astm/identifiers/adjunct.rb +0 -8
- data/lib/pubid/astm/identifiers/data_series.rb +0 -14
- data/lib/pubid/astm/identifiers/iso_dual_published.rb +9 -34
- data/lib/pubid/astm/identifiers/manual.rb +0 -27
- data/lib/pubid/astm/identifiers/monograph.rb +0 -14
- data/lib/pubid/astm/identifiers/research_report.rb +0 -7
- data/lib/pubid/astm/identifiers/standard.rb +0 -39
- data/lib/pubid/astm/identifiers/technical_report.rb +0 -13
- data/lib/pubid/astm/identifiers/work_in_progress.rb +0 -11
- data/lib/pubid/astm/identifiers.rb +18 -0
- data/lib/pubid/astm/renderer.rb +172 -0
- data/lib/pubid/astm/single_identifier.rb +3 -11
- data/lib/pubid/astm/urn_parser.rb +30 -0
- data/lib/pubid/astm.rb +39 -27
- data/lib/pubid/bsi/builder.rb +21 -12
- data/lib/pubid/bsi/identifier.rb +5 -85
- data/lib/pubid/bsi/identifiers/addendum_document.rb +2 -36
- data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +8 -48
- data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +8 -39
- data/lib/pubid/bsi/identifiers/aerospace_standard.rb +2 -55
- data/lib/pubid/bsi/identifiers/amendment.rb +2 -22
- data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +1 -6
- data/lib/pubid/bsi/identifiers/british_standard.rb +2 -1
- data/lib/pubid/bsi/identifiers/bundled_identifier.rb +3 -87
- data/lib/pubid/bsi/identifiers/committee_document.rb +0 -16
- data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +3 -87
- data/lib/pubid/bsi/identifiers/corrigendum.rb +2 -10
- data/lib/pubid/bsi/identifiers/detailed_specification.rb +0 -36
- data/lib/pubid/bsi/identifiers/disc.rb +0 -29
- data/lib/pubid/bsi/identifiers/draft_document.rb +2 -46
- data/lib/pubid/bsi/identifiers/electronic_book.rb +2 -38
- data/lib/pubid/bsi/identifiers/expert_commentary.rb +2 -18
- data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +0 -47
- data/lib/pubid/bsi/identifiers/flex.rb +0 -35
- data/lib/pubid/bsi/identifiers/handbook.rb +1 -15
- data/lib/pubid/bsi/identifiers/index.rb +0 -32
- data/lib/pubid/bsi/identifiers/method.rb +0 -41
- data/lib/pubid/bsi/identifiers/national_annex.rb +4 -29
- data/lib/pubid/bsi/identifiers/practice_guide.rb +1 -6
- data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +2 -54
- data/lib/pubid/bsi/identifiers/published_document.rb +2 -54
- data/lib/pubid/bsi/identifiers/section.rb +0 -30
- data/lib/pubid/bsi/identifiers/set.rb +3 -20
- data/lib/pubid/bsi/identifiers/standalone_amendment.rb +0 -9
- data/lib/pubid/bsi/identifiers/supplement_document.rb +2 -24
- data/lib/pubid/bsi/identifiers/supplementary_index.rb +0 -46
- data/lib/pubid/bsi/identifiers/technical_specification.rb +2 -47
- data/lib/pubid/bsi/identifiers/test_method.rb +0 -32
- data/lib/pubid/bsi/identifiers/value_added_publication.rb +2 -17
- data/lib/pubid/bsi/identifiers.rb +0 -1
- data/lib/pubid/bsi/renderer.rb +1050 -0
- data/lib/pubid/bsi/single_identifier.rb +33 -78
- data/lib/pubid/bsi/urn_generator.rb +2 -3
- data/lib/pubid/bsi/urn_parser.rb +52 -0
- data/lib/pubid/bsi.rb +232 -2
- data/lib/pubid/builder/base.rb +57 -10
- data/lib/pubid/bundled_identifier.rb +0 -1
- data/lib/pubid/ccsds/builder.rb +4 -3
- data/lib/pubid/ccsds/identifier.rb +53 -68
- data/lib/pubid/ccsds/identifiers/base.rb +11 -61
- data/lib/pubid/ccsds/identifiers/corrigendum.rb +7 -6
- data/lib/pubid/ccsds/parser.rb +4 -2
- data/lib/pubid/ccsds/supplement_identifier.rb +15 -11
- data/lib/pubid/ccsds/urn_generator.rb +3 -3
- data/lib/pubid/ccsds/urn_parser.rb +20 -0
- data/lib/pubid/ccsds.rb +39 -1
- data/lib/pubid/cen_cenelec/builder.rb +12 -14
- data/lib/pubid/cen_cenelec/identifier.rb +11 -40
- data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +9 -4
- data/lib/pubid/cen_cenelec/identifiers/amendment.rb +0 -10
- data/lib/pubid/cen_cenelec/identifiers/base.rb +2 -45
- data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +2 -1
- data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +2 -1
- data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +0 -27
- data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +0 -15
- data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +2 -1
- data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +2 -8
- data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +2 -1
- data/lib/pubid/cen_cenelec/identifiers/fragment.rb +0 -4
- data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +2 -1
- data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +2 -1
- data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +2 -1
- data/lib/pubid/cen_cenelec/renderer.rb +261 -0
- data/lib/pubid/cen_cenelec/single_identifier.rb +9 -90
- data/lib/pubid/cen_cenelec/urn_generator.rb +6 -6
- data/lib/pubid/cen_cenelec/urn_parser.rb +28 -0
- data/lib/pubid/cen_cenelec.rb +172 -1
- data/lib/pubid/cie/components/code.rb +8 -0
- data/lib/pubid/cie/identifier.rb +10 -57
- data/lib/pubid/cie/single_identifier.rb +4 -4
- data/lib/pubid/cie/urn_parser.rb +28 -0
- data/lib/pubid/cie.rb +47 -1
- data/lib/pubid/components/adoption.rb +104 -0
- data/lib/pubid/components/code.rb +22 -8
- data/lib/pubid/components/date.rb +23 -16
- data/lib/pubid/components/edition.rb +9 -6
- data/lib/pubid/components/iteration.rb +32 -0
- data/lib/pubid/components/language.rb +6 -4
- data/lib/pubid/components/locality.rb +10 -1
- data/lib/pubid/components/publisher.rb +9 -6
- data/lib/pubid/components/relationship.rb +151 -0
- data/lib/pubid/components/stage.rb +5 -14
- data/lib/pubid/components/supplement.rb +184 -0
- data/lib/pubid/components/type.rb +5 -15
- data/lib/pubid/components/typed_stage.rb +10 -11
- data/lib/pubid/components.rb +4 -1
- data/lib/pubid/core/update_codes.rb +28 -7
- data/lib/pubid/csa/identifier.rb +9 -59
- data/lib/pubid/csa/identifiers/base.rb +0 -123
- data/lib/pubid/csa/identifiers/cec.rb +0 -103
- data/lib/pubid/csa/identifiers/series.rb +0 -104
- data/lib/pubid/csa/renderer.rb +292 -0
- data/lib/pubid/csa/single_identifier.rb +1 -1
- data/lib/pubid/csa/urn_generator.rb +1 -1
- data/lib/pubid/csa/urn_parser.rb +33 -0
- data/lib/pubid/csa.rb +46 -1
- data/lib/pubid/etsi/components/code.rb +10 -9
- data/lib/pubid/etsi/components/version.rb +0 -5
- data/lib/pubid/etsi/identifier.rb +4 -55
- data/lib/pubid/etsi/identifiers/base.rb +31 -27
- data/lib/pubid/etsi/identifiers/supplement_identifier.rb +1 -11
- data/lib/pubid/etsi/renderer.rb +42 -0
- data/lib/pubid/etsi/urn_parser.rb +34 -0
- data/lib/pubid/etsi.rb +44 -1
- data/lib/pubid/export/exporter.rb +4 -46
- data/lib/pubid/export/flavor_exporter.rb +111 -278
- data/lib/pubid/export.rb +0 -6
- data/lib/pubid/identifier.rb +92 -18
- data/lib/pubid/identifier_metadata.rb +1 -1
- data/lib/pubid/idf/builder.rb +3 -3
- data/lib/pubid/idf/identifier.rb +7 -66
- data/lib/pubid/idf/identifiers/amendment.rb +2 -1
- data/lib/pubid/idf/identifiers/corrigendum.rb +2 -1
- data/lib/pubid/idf/identifiers/international_standard.rb +2 -1
- data/lib/pubid/idf/identifiers/reviewed_method.rb +2 -1
- data/lib/pubid/idf/parser.rb +3 -2
- data/lib/pubid/idf/renderer.rb +84 -0
- data/lib/pubid/idf/supplement_identifier.rb +2 -10
- data/lib/pubid/idf/urn_generator.rb +4 -39
- data/lib/pubid/idf/urn_parser.rb +25 -0
- data/lib/pubid/idf.rb +55 -1
- data/lib/pubid/iec/builder.rb +46 -64
- data/lib/pubid/iec/components/code.rb +8 -32
- data/lib/pubid/iec/components/publisher.rb +0 -1
- data/lib/pubid/iec/components.rb +14 -0
- data/lib/pubid/iec/identifier.rb +251 -213
- data/lib/pubid/iec/identifiers/amendment.rb +2 -3
- data/lib/pubid/iec/identifiers/base.rb +5 -33
- data/lib/pubid/iec/identifiers/component_specification.rb +3 -3
- data/lib/pubid/iec/identifiers/conformity_assessment.rb +1 -2
- data/lib/pubid/iec/identifiers/consolidated_identifier.rb +23 -26
- data/lib/pubid/iec/identifiers/corrigendum.rb +2 -3
- data/lib/pubid/iec/identifiers/fragment_identifier.rb +35 -24
- data/lib/pubid/iec/identifiers/guide.rb +0 -2
- data/lib/pubid/iec/identifiers/international_standard.rb +2 -3
- data/lib/pubid/iec/identifiers/interpretation_sheet.rb +2 -3
- data/lib/pubid/iec/identifiers/operational_document.rb +3 -3
- data/lib/pubid/iec/identifiers/publicly_available_specification.rb +2 -3
- data/lib/pubid/iec/identifiers/sheet_identifier.rb +17 -11
- data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +3 -3
- data/lib/pubid/iec/identifiers/systems_reference_document.rb +2 -3
- data/lib/pubid/iec/identifiers/technical_report.rb +2 -3
- data/lib/pubid/iec/identifiers/technical_specification.rb +2 -3
- data/lib/pubid/iec/identifiers/technology_report.rb +1 -2
- data/lib/pubid/iec/identifiers/test_report_form.rb +3 -35
- data/lib/pubid/iec/identifiers/vap_identifier.rb +24 -21
- data/lib/pubid/iec/identifiers/white_paper.rb +3 -3
- data/lib/pubid/iec/identifiers/working_document.rb +2 -50
- data/lib/pubid/iec/identifiers.rb +30 -0
- data/lib/pubid/iec/parser.rb +13 -12
- data/lib/pubid/iec/renderer.rb +254 -0
- data/lib/pubid/iec/single_identifier.rb +6 -12
- data/lib/pubid/iec/supplement_identifier.rb +58 -54
- data/lib/pubid/iec/urn_generator.rb +3 -3
- data/lib/pubid/iec/urn_parser.rb +3 -3
- data/lib/pubid/iec.rb +43 -67
- data/lib/pubid/ieee/builder.rb +12 -12
- data/lib/pubid/ieee/components/code.rb +8 -0
- data/lib/pubid/ieee/components/draft.rb +14 -0
- data/lib/pubid/ieee/components/relationship.rb +5 -149
- data/lib/pubid/ieee/identifier.rb +5 -52
- data/lib/pubid/ieee/identifiers/adopted_standard.rb +0 -9
- data/lib/pubid/ieee/identifiers/base.rb +221 -556
- data/lib/pubid/ieee/identifiers/conformance_identifier.rb +0 -10
- data/lib/pubid/ieee/identifiers/corrigendum.rb +0 -12
- data/lib/pubid/ieee/identifiers/csa_dual_published.rb +0 -10
- data/lib/pubid/ieee/identifiers/dual_identifier.rb +0 -4
- data/lib/pubid/ieee/identifiers/dual_published.rb +0 -4
- data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +0 -9
- data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +0 -10
- data/lib/pubid/ieee/identifiers/joint_development.rb +2 -0
- data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +0 -18
- data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +0 -6
- data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +15 -0
- data/lib/pubid/ieee/identifiers/redlined_standard.rb +0 -7
- data/lib/pubid/ieee/identifiers/si_standard.rb +0 -38
- data/lib/pubid/ieee/identifiers/standard.rb +1 -1
- data/lib/pubid/ieee/pre_parser.rb +301 -0
- data/lib/pubid/ieee/renderer.rb +307 -0
- data/lib/pubid/ieee/urn_parser.rb +34 -0
- data/lib/pubid/ieee.rb +66 -1
- data/lib/pubid/ieee_debug.rb +0 -1
- data/lib/pubid/iho/builder.rb +2 -2
- data/lib/pubid/iho/identifier.rb +7 -59
- data/lib/pubid/iho/identifiers/base.rb +64 -31
- data/lib/pubid/iho/parser.rb +3 -3
- data/lib/pubid/iho/renderer.rb +30 -0
- data/lib/pubid/iho/urn_generator.rb +2 -2
- data/lib/pubid/iho/urn_parser.rb +58 -0
- data/lib/pubid/iho.rb +52 -1
- data/lib/pubid/iso/builder.rb +55 -53
- data/lib/pubid/iso/bundled_identifier.rb +51 -0
- data/lib/pubid/iso/components/code.rb +7 -19
- data/lib/pubid/iso/components/publisher.rb +10 -8
- data/lib/pubid/iso/components.rb +2 -4
- data/lib/pubid/iso/identifier.rb +219 -252
- data/lib/pubid/iso/identifiers/addendum.rb +9 -6
- data/lib/pubid/iso/identifiers/amendment.rb +8 -4
- data/lib/pubid/iso/identifiers/corrigendum.rb +4 -4
- data/lib/pubid/iso/identifiers/data.rb +0 -1
- data/lib/pubid/iso/identifiers/directives.rb +8 -2
- data/lib/pubid/iso/identifiers/directives_supplement.rb +43 -14
- data/lib/pubid/iso/identifiers/extract.rb +2 -2
- data/lib/pubid/iso/identifiers/guide.rb +0 -1
- data/lib/pubid/iso/identifiers/international_standard.rb +4 -4
- data/lib/pubid/iso/identifiers/international_standardized_profile.rb +4 -4
- data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +10 -4
- data/lib/pubid/iso/identifiers/pas.rb +2 -2
- data/lib/pubid/iso/identifiers/recommendation.rb +2 -2
- data/lib/pubid/iso/identifiers/supplement.rb +11 -3
- data/lib/pubid/iso/identifiers/tc_document.rb +44 -15
- data/lib/pubid/iso/identifiers/technical_report.rb +4 -4
- data/lib/pubid/iso/identifiers/technical_specification.rb +2 -2
- data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +2 -2
- data/lib/pubid/iso/identifiers.rb +0 -1
- data/lib/pubid/iso/normalizer.rb +89 -0
- data/lib/pubid/iso/parser.rb +22 -4
- data/lib/pubid/iso/single_identifier.rb +0 -4
- data/lib/pubid/iso/supplement_identifier.rb +15 -2
- data/lib/pubid/iso/urn_generator.rb +66 -182
- data/lib/pubid/iso/urn_parser.rb +12 -7
- data/lib/pubid/iso.rb +177 -2
- data/lib/pubid/itu/builder.rb +0 -12
- data/lib/pubid/itu/components/code.rb +9 -7
- data/lib/pubid/itu/components/sector.rb +15 -4
- data/lib/pubid/itu/components/series.rb +0 -4
- data/lib/pubid/itu/components.rb +11 -0
- data/lib/pubid/itu/identifier.rb +4 -116
- data/lib/pubid/itu/identifiers/amendment.rb +0 -2
- data/lib/pubid/itu/identifiers/annex.rb +0 -2
- data/lib/pubid/itu/identifiers/base.rb +124 -128
- data/lib/pubid/itu/identifiers/combined_identifier.rb +0 -2
- data/lib/pubid/itu/identifiers/corrigendum.rb +0 -2
- data/lib/pubid/itu/identifiers/recommendation.rb +0 -2
- data/lib/pubid/itu/identifiers/special_publication.rb +0 -2
- data/lib/pubid/itu/identifiers/supplement.rb +0 -2
- data/lib/pubid/itu/urn_parser.rb +23 -0
- data/lib/pubid/itu.rb +44 -1
- data/lib/pubid/jcgm/builder.rb +16 -8
- data/lib/pubid/jcgm/identifier.rb +0 -43
- data/lib/pubid/jcgm/identifiers/amendment.rb +0 -9
- data/lib/pubid/jcgm/identifiers/gum_guide.rb +0 -12
- data/lib/pubid/jcgm/renderer.rb +68 -0
- data/lib/pubid/jcgm/single_identifier.rb +0 -8
- data/lib/pubid/jcgm/urn_generator.rb +4 -6
- data/lib/pubid/jcgm/urn_parser.rb +23 -0
- data/lib/pubid/jcgm.rb +43 -2
- data/lib/pubid/jis/builder.rb +44 -52
- data/lib/pubid/jis/identifier.rb +120 -46
- data/lib/pubid/jis/identifiers/amendment.rb +1 -1
- data/lib/pubid/jis/identifiers/corrigendum.rb +16 -0
- data/lib/pubid/jis/identifiers/standard.rb +2 -1
- data/lib/pubid/jis/identifiers/technical_report.rb +2 -1
- data/lib/pubid/jis/identifiers/technical_specification.rb +2 -1
- data/lib/pubid/jis/identifiers.rb +1 -1
- data/lib/pubid/jis/parser.rb +31 -5
- data/lib/pubid/jis/renderer.rb +69 -0
- data/lib/pubid/jis/single_identifier.rb +6 -12
- data/lib/pubid/jis/supplement_identifier.rb +17 -14
- data/lib/pubid/jis/urn_parser.rb +23 -0
- data/lib/pubid/jis.rb +42 -2
- data/lib/pubid/nist/builder.rb +63 -1871
- data/lib/pubid/nist/caster.rb +1272 -0
- data/lib/pubid/nist/circular_supplement_builder.rb +291 -0
- data/lib/pubid/nist/components/code.rb +9 -20
- data/lib/pubid/nist/components/supplement.rb +2 -2
- data/lib/pubid/nist/components.rb +0 -1
- data/lib/pubid/nist/identifier.rb +8 -60
- data/lib/pubid/nist/identifiers/base.rb +564 -492
- data/lib/pubid/nist/identifiers/circular.rb +7 -2
- data/lib/pubid/nist/identifiers/circular_supplement.rb +2 -1
- data/lib/pubid/nist/identifiers/commercial_standard.rb +2 -1
- data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +6 -4
- data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +10 -3
- data/lib/pubid/nist/identifiers/crpl_report.rb +8 -8
- data/lib/pubid/nist/identifiers/dated_document.rb +49 -0
- data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +15 -24
- data/lib/pubid/nist/identifiers/grant_contractor_report.rb +2 -1
- data/lib/pubid/nist/identifiers/handbook.rb +2 -1
- data/lib/pubid/nist/identifiers/internal_report.rb +2 -1
- data/lib/pubid/nist/identifiers/letter_circular.rb +2 -1
- data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +5 -4
- data/lib/pubid/nist/identifiers/monograph.rb +7 -3
- data/lib/pubid/nist/identifiers/report.rb +4 -2
- data/lib/pubid/nist/identifiers/special_publication.rb +2 -1
- data/lib/pubid/nist/identifiers/technical_note.rb +3 -2
- data/lib/pubid/nist/identifiers.rb +1 -0
- data/lib/pubid/nist/parser.rb +62 -452
- data/lib/pubid/nist/parser_output_normalizer.rb +233 -0
- data/lib/pubid/nist/preprocessor.rb +428 -0
- data/lib/pubid/nist/renderer.rb +43 -0
- data/lib/pubid/nist/router.rb +148 -0
- data/lib/pubid/nist/series/base.rb +58 -0
- data/lib/pubid/nist/series/crpl.rb +13 -0
- data/lib/pubid/nist/series/fips.rb +14 -0
- data/lib/pubid/nist/series/ir.rb +60 -0
- data/lib/pubid/nist/series/letter_preserving.rb +15 -0
- data/lib/pubid/nist/series/mono.rb +19 -0
- data/lib/pubid/nist/series/ncstar.rb +20 -0
- data/lib/pubid/nist/series.rb +49 -0
- data/lib/pubid/nist/supplement_identifier.rb +3 -1
- data/lib/pubid/nist/urn_parser.rb +67 -0
- data/lib/pubid/nist.rb +86 -4
- data/lib/pubid/oiml/builder.rb +21 -3
- data/lib/pubid/oiml/components/code.rb +17 -0
- data/lib/pubid/oiml/identifier.rb +40 -46
- data/lib/pubid/oiml/identifiers/annex.rb +13 -46
- data/lib/pubid/oiml/identifiers/errata.rb +15 -0
- data/lib/pubid/oiml/identifiers.rb +1 -1
- data/lib/pubid/oiml/parser.rb +59 -12
- data/lib/pubid/oiml/renderer.rb +171 -0
- data/lib/pubid/oiml/single_identifier.rb +61 -42
- data/lib/pubid/oiml/supplement_identifier.rb +31 -17
- data/lib/pubid/oiml/urn_generator.rb +0 -8
- data/lib/pubid/oiml/urn_parser.rb +22 -0
- data/lib/pubid/oiml.rb +42 -1
- data/lib/pubid/plateau/identifier.rb +4 -55
- data/lib/pubid/plateau/identifiers/base.rb +45 -36
- data/lib/pubid/plateau/identifiers/handbook.rb +0 -6
- data/lib/pubid/plateau/identifiers/technical_report.rb +0 -4
- data/lib/pubid/plateau/renderer.rb +51 -0
- data/lib/pubid/plateau/supplement_identifier.rb +0 -4
- data/lib/pubid/plateau/urn_parser.rb +43 -0
- data/lib/pubid/plateau.rb +43 -1
- data/lib/pubid/renderers/directives_renderer.rb +22 -8
- data/lib/pubid/renderers/guide_renderer.rb +4 -2
- data/lib/pubid/renderers/human_readable.rb +18 -7
- data/lib/pubid/rendering/context.rb +28 -19
- data/lib/pubid/rendering.rb +0 -3
- data/lib/pubid/sae/components/date.rb +8 -0
- data/lib/pubid/sae/components/type.rb +5 -1
- data/lib/pubid/sae/identifier.rb +4 -35
- data/lib/pubid/sae/identifiers/base.rb +26 -31
- data/lib/pubid/sae/renderer.rb +36 -0
- data/lib/pubid/sae/urn_generator.rb +2 -10
- data/lib/pubid/sae/urn_parser.rb +36 -0
- data/lib/pubid/sae.rb +42 -1
- data/lib/pubid/urn_generator/base.rb +12 -12
- data/lib/pubid/urn_parser/base.rb +81 -0
- data/lib/pubid/urn_parser/errors.rb +9 -0
- data/lib/pubid/urn_parser.rb +14 -0
- data/lib/pubid/version.rb +1 -1
- data/lib/pubid.rb +45 -7
- data/lib/tasks/export.rake +6 -5
- data/lib/tasks/website-data.json +1940 -1882
- metadata +75 -45
- data/lib/pubid/amca/scheme.rb +0 -16
- data/lib/pubid/ansi/scheme.rb +0 -15
- data/lib/pubid/api/scheme.rb +0 -66
- data/lib/pubid/ashrae/scheme.rb +0 -53
- data/lib/pubid/asme/scheme.rb +0 -37
- data/lib/pubid/astm/scheme.rb +0 -55
- data/lib/pubid/bsi/identifiers/base.rb +0 -11
- data/lib/pubid/bsi/scheme.rb +0 -243
- data/lib/pubid/ccsds/scheme.rb +0 -57
- data/lib/pubid/cen_cenelec/scheme.rb +0 -164
- data/lib/pubid/cie/scheme.rb +0 -64
- data/lib/pubid/components/factory.rb +0 -50
- data/lib/pubid/csa/scheme.rb +0 -44
- data/lib/pubid/etsi/scheme.rb +0 -42
- data/lib/pubid/export/data_class_exporter.rb +0 -59
- data/lib/pubid/export/ieee_exporter.rb +0 -78
- data/lib/pubid/export/itu_exporter.rb +0 -66
- data/lib/pubid/export/nist_exporter.rb +0 -64
- data/lib/pubid/export/registry_exporter.rb +0 -90
- data/lib/pubid/export/scheme_exporter.rb +0 -70
- data/lib/pubid/identifier_registry.rb +0 -198
- data/lib/pubid/idf/scheme.rb +0 -61
- data/lib/pubid/iec/scheme.rb +0 -71
- data/lib/pubid/ieee/scheme.rb +0 -90
- data/lib/pubid/iho/scheme.rb +0 -29
- data/lib/pubid/iso/identifiers/base.rb +0 -115
- data/lib/pubid/iso/scheme.rb +0 -193
- data/lib/pubid/itu/scheme.rb +0 -174
- data/lib/pubid/jcgm/scheme.rb +0 -60
- data/lib/pubid/jis/components/code.rb +0 -59
- data/lib/pubid/jis/identifiers/base.rb +0 -72
- data/lib/pubid/jis/scheme.rb +0 -49
- data/lib/pubid/nist/components/publisher.rb +0 -24
- data/lib/pubid/nist/scheme.rb +0 -199
- data/lib/pubid/oiml/identifiers/base.rb +0 -36
- data/lib/pubid/oiml/scheme.rb +0 -46
- data/lib/pubid/plateau/scheme.rb +0 -45
- data/lib/pubid/rendering/base.rb +0 -73
- data/lib/pubid/rendering/common.rb +0 -211
- data/lib/pubid/rendering/format.rb +0 -25
- data/lib/pubid/sae/scheme.rb +0 -47
- data/lib/pubid/scheme.rb +0 -219
|
@@ -2,577 +2,649 @@
|
|
|
2
2
|
|
|
3
3
|
module Pubid
|
|
4
4
|
module Nist
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
# NIST/NBS flavor base class. Canonical name Pubid::Nist::Identifier; every
|
|
6
|
+
# concrete NIST identifier (Identifiers::*) descends from it, and
|
|
7
|
+
# Identifiers::Base — aliased at the foot of this file — points back to it
|
|
8
|
+
# for backward compatibility. Being a real Pubid::Identifier subclass gives
|
|
9
|
+
# native `is_a?` identity and the shared polymorphic `from_hash`.
|
|
10
|
+
class Identifier < ::Pubid::Identifier
|
|
11
|
+
# Delegate to the flavor module so callers can use
|
|
12
|
+
# `Pubid::Nist::Identifier.parse` consistently with other flavors.
|
|
13
|
+
def self.parse(identifier)
|
|
14
|
+
Pubid::Nist.parse(identifier)
|
|
15
|
+
end
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
attribute :publisher, Components::Publisher
|
|
19
|
-
attribute :series, Components::Code # Set by Builder from parsed data
|
|
20
|
-
attribute :number, Components::Code
|
|
21
|
-
|
|
22
|
-
# V2 COMPONENTS (Lutaml::Model objects) - PROPER SEPARATION
|
|
23
|
-
attribute :edition, Components::Edition # Edition (type + id): e2, e2021, r5, -3
|
|
24
|
-
attribute :edition_component, Components::Edition # V2 edition component (alias)
|
|
25
|
-
attribute :volume, Components::Volume # Volume component (v6)
|
|
26
|
-
attribute :part, Components::Part # Part component (n1 or pt1)
|
|
27
|
-
attribute :stage, Components::Stage
|
|
28
|
-
attribute :version_component, Components::Version
|
|
29
|
-
attribute :update_component, Components::Update
|
|
30
|
-
attribute :translation_component, Components::Translation
|
|
31
|
-
attribute :issue_number, Components::IssueNumber
|
|
32
|
-
attribute :parsed_format, :string # :mr, :short, :long, :abbrev
|
|
33
|
-
attribute :publisher_was_parsed, :boolean, default: -> { false }
|
|
34
|
-
|
|
35
|
-
# LEGACY attributes (keep for backward compatibility during migration)
|
|
36
|
-
attribute :parts, Components::Code, collection: true
|
|
37
|
-
attribute :revision, :string
|
|
38
|
-
attribute :revision_year, :string # Year for revision (e.g., r6/1925, r1963, rJun1992)
|
|
39
|
-
attribute :revision_month, :string # Month for revision (e.g., rJun1992)
|
|
40
|
-
attribute :edition_year, :string # Legacy edition year for backward compatibility
|
|
41
|
-
attribute :version, :string
|
|
42
|
-
attribute :update, Components::Update
|
|
43
|
-
attribute :year, :integer
|
|
44
|
-
attribute :month, :integer
|
|
45
|
-
|
|
46
|
-
# Additional attributes for complex patterns
|
|
47
|
-
attribute :first_number, Components::Code
|
|
48
|
-
attribute :second_number, Components::Code
|
|
49
|
-
attribute :update_number, :string
|
|
50
|
-
attribute :update_year, :string
|
|
51
|
-
attribute :addendum, :string
|
|
52
|
-
attribute :addendum_number, :string
|
|
53
|
-
# Single source of truth for the supplement: a structured component with
|
|
54
|
-
# isolated parts (number / year / month / date-range / revision), so a
|
|
55
|
-
# supplement's year is queryable independently of its number. Presence
|
|
56
|
-
# (non-nil) means "is a supplement"; an all-empty component is a bare
|
|
57
|
-
# "sup" marker. Replaces the former flat :supplement string plus the
|
|
58
|
-
# separate date-range/has_revision fields.
|
|
59
|
-
attribute :supplement, Components::Supplement
|
|
60
|
-
attribute :errata, :string
|
|
61
|
-
attribute :index, :string
|
|
62
|
-
attribute :insert, :string
|
|
63
|
-
attribute :section, :string
|
|
64
|
-
attribute :appendix, :string
|
|
65
|
-
attribute :translation, :string
|
|
66
|
-
attribute :draft, :string
|
|
67
|
-
attribute :draft_number, :string # For -draft N → N pd rendering
|
|
68
|
-
|
|
69
|
-
# Default series_code — subclasses override to provide a normalized series name.
|
|
70
|
-
def series_code
|
|
71
|
-
nil
|
|
72
|
-
end
|
|
17
|
+
# Default: no typed stages. Subclasses override as needed.
|
|
18
|
+
def self.typed_stages
|
|
19
|
+
[]
|
|
20
|
+
end
|
|
73
21
|
|
|
74
|
-
|
|
75
|
-
|
|
22
|
+
# Generate URN for this identifier
|
|
23
|
+
#
|
|
24
|
+
# @return [String] URN representation
|
|
25
|
+
|
|
26
|
+
# Plain string ("NIST"/"NBS"), not a Components::Publisher wrapper: the
|
|
27
|
+
# value is a single token, so a string serializes flat
|
|
28
|
+
# (`publisher: NBS`, not `publisher: {publisher: NBS}`) and accepts the
|
|
29
|
+
# raw string the circular/supplement builders pass straight through.
|
|
30
|
+
attribute :publisher, :string
|
|
31
|
+
attribute :series, Components::Code # Set by Builder from parsed data
|
|
32
|
+
attribute :number, Components::Code
|
|
33
|
+
|
|
34
|
+
# V2 COMPONENTS (Lutaml::Model objects) - PROPER SEPARATION
|
|
35
|
+
attribute :edition, Components::Edition # Edition (type + id): e2, e2021, r5, -3
|
|
36
|
+
attribute :edition_component, Components::Edition # V2 edition component (alias)
|
|
37
|
+
attribute :volume, Components::Volume # Volume component (v6)
|
|
38
|
+
attribute :part, Components::Part # Part component (n1 or pt1)
|
|
39
|
+
attribute :stage, Components::Stage
|
|
40
|
+
attribute :version_component, Components::Version
|
|
41
|
+
attribute :update_component, Components::Update
|
|
42
|
+
attribute :translation_component, Components::Translation
|
|
43
|
+
attribute :issue_number, Components::IssueNumber
|
|
44
|
+
attribute :parsed_format, :string # :mr, :short, :long, :abbrev
|
|
45
|
+
# Whether the publisher prefix (NIST/NBS) should be rendered. Defaults
|
|
46
|
+
# to true so the common publisher-bearing id need not serialize the
|
|
47
|
+
# flag at all — the Builder only assigns it (false) for prefix-less
|
|
48
|
+
# inputs, so `to_hash` carries `publisher_was_parsed: false` only in
|
|
49
|
+
# that case and omits it otherwise. (lutaml emits a boolean iff it was
|
|
50
|
+
# explicitly assigned; an omitted key loads as this default.)
|
|
51
|
+
attribute :publisher_was_parsed, :boolean, default: -> { true }
|
|
52
|
+
|
|
53
|
+
# LEGACY attributes (keep for backward compatibility during migration)
|
|
54
|
+
attribute :parts, Components::Code, collection: true
|
|
55
|
+
attribute :revision, :string
|
|
56
|
+
attribute :revision_year, :string # Year for revision (e.g., r6/1925, r1963, rJun1992)
|
|
57
|
+
attribute :revision_month, :string # Month for revision (e.g., rJun1992)
|
|
58
|
+
attribute :edition_year, :string # Legacy edition year for backward compatibility
|
|
59
|
+
attribute :version, :string
|
|
60
|
+
attribute :update, Components::Update
|
|
61
|
+
attribute :year, :integer
|
|
62
|
+
attribute :month, :integer
|
|
63
|
+
|
|
64
|
+
# Additional attributes for complex patterns
|
|
65
|
+
attribute :first_number, Components::Code
|
|
66
|
+
attribute :second_number, Components::Code
|
|
67
|
+
attribute :update_number, :string
|
|
68
|
+
attribute :update_year, :string
|
|
69
|
+
attribute :addendum, :string
|
|
70
|
+
attribute :addendum_number, :string
|
|
71
|
+
# Single source of truth for the supplement: a structured component with
|
|
72
|
+
# isolated parts (number / year / month / date-range / revision), so a
|
|
73
|
+
# supplement's year is queryable independently of its number. Presence
|
|
74
|
+
# (non-nil) means "is a supplement"; an all-empty component is a bare
|
|
75
|
+
# "sup" marker. Replaces the former flat :supplement string plus the
|
|
76
|
+
# separate date-range/has_revision fields.
|
|
77
|
+
attribute :supplement, Components::Supplement
|
|
78
|
+
attribute :errata, :string
|
|
79
|
+
attribute :index, :string
|
|
80
|
+
attribute :insert, :string
|
|
81
|
+
attribute :section, :string
|
|
82
|
+
attribute :appendix, :string
|
|
83
|
+
attribute :translation, :string
|
|
84
|
+
attribute :draft, :string
|
|
85
|
+
attribute :draft_number, :string # For -draft N → N pd rendering
|
|
86
|
+
|
|
87
|
+
# Default series_code — subclasses override to provide a normalized series name.
|
|
88
|
+
def series_code
|
|
89
|
+
nil
|
|
90
|
+
end
|
|
76
91
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
next if value.nil?
|
|
92
|
+
def initialize(**attributes)
|
|
93
|
+
super()
|
|
80
94
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
95
|
+
attrs = self.class.attributes
|
|
96
|
+
attributes.each do |key, value|
|
|
97
|
+
next if value.nil?
|
|
84
98
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
# See lib/pubid/nist/builder.rb lines 368-472 for compound number logic
|
|
99
|
+
setter = :"#{key}="
|
|
100
|
+
public_send(setter, value) if attrs.key?(key)
|
|
88
101
|
end
|
|
89
102
|
|
|
90
|
-
#
|
|
91
|
-
#
|
|
92
|
-
#
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
103
|
+
# NOTE: Compound number building is handled by the Builder class
|
|
104
|
+
# Do NOT build compound numbers here - let the builder apply special patterns first
|
|
105
|
+
# See lib/pubid/nist/builder.rb lines 368-472 for compound number logic
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Attributes that are build artifacts or rendering aliases, not part
|
|
109
|
+
# of an identifier's logical identity. They diverge between equally-
|
|
110
|
+
# valid spellings of the same id (e.g. long "Rev. 1" vs short "r1"):
|
|
111
|
+
# - edition_component: redundant alias of :edition
|
|
112
|
+
# - first_number/second_number: decomposed parts of the canonical
|
|
113
|
+
# :number, retained from the parse for building
|
|
114
|
+
# - parsed_format: records the input format for round-trip rendering
|
|
115
|
+
EQUALITY_IGNORED_ATTRS = %i[
|
|
116
|
+
edition_component first_number second_number parsed_format
|
|
117
|
+
].freeze
|
|
118
|
+
|
|
119
|
+
# Logical identity comparison: equal when every attribute except the
|
|
120
|
+
# build artifacts/aliases above matches. (Edition#== already ignores
|
|
121
|
+
# its rendering-only original_prefix.)
|
|
122
|
+
def ==(other)
|
|
123
|
+
return false unless other.instance_of?(self.class)
|
|
124
|
+
|
|
125
|
+
self.class.attributes.each_key.all? do |name|
|
|
126
|
+
EQUALITY_IGNORED_ATTRS.include?(name) || public_send(name) == other.public_send(name)
|
|
110
127
|
end
|
|
128
|
+
end
|
|
111
129
|
|
|
112
|
-
|
|
130
|
+
alias eql? ==
|
|
113
131
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
132
|
+
def hash
|
|
133
|
+
vals = self.class.attributes.each_key.reject do |name|
|
|
134
|
+
EQUALITY_IGNORED_ATTRS.include?(name)
|
|
135
|
+
end.map { |name| public_send(name) }
|
|
136
|
+
[self.class, *vals].hash
|
|
137
|
+
end
|
|
120
138
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
# Wildcard / partial-identifier match. Treats +self+ as a QUERY pattern
|
|
140
|
+
# and +candidate+ as a concrete document: every ID part SET on the query
|
|
141
|
+
# must equal the candidate's, while parts left unset (nil/empty) are
|
|
142
|
+
# wildcards that match any value. So a query carrying no edition and no
|
|
143
|
+
# supplement matches that document across ALL editions, years, and
|
|
144
|
+
# supplements — the basis for "select docs by ID parts".
|
|
145
|
+
#
|
|
146
|
+
# Asymmetric (unlike ==): "NBS CIRC 25".matches?("NBS CIRC 25sup1924")
|
|
147
|
+
# is true, but not the reverse. The candidate must be the same class or
|
|
148
|
+
# a subclass so series-level identity still holds.
|
|
149
|
+
def matches?(candidate)
|
|
150
|
+
return false unless candidate.is_a?(self.class)
|
|
151
|
+
|
|
152
|
+
self.class.attributes.each_key.all? do |name|
|
|
153
|
+
next true if EQUALITY_IGNORED_ATTRS.include?(name)
|
|
154
|
+
|
|
155
|
+
query_val = public_send(name)
|
|
156
|
+
next true if query_val.nil?
|
|
157
|
+
next true if query_val.is_a?(String) && query_val.empty?
|
|
158
|
+
next true if query_val.is_a?(Array) && query_val.empty?
|
|
159
|
+
|
|
160
|
+
query_val == candidate.public_send(name)
|
|
143
161
|
end
|
|
162
|
+
end
|
|
144
163
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
end
|
|
158
|
-
self.class.new(**attrs)
|
|
164
|
+
# Return a copy with the named attributes nil'd. Overrides
|
|
165
|
+
# Pubid::Identifier#exclude because NIST's initialize is keyword-only
|
|
166
|
+
# (initialize(**attributes)) while the inherited exclude rebuilds via
|
|
167
|
+
# the positional self.class.new(attrs) form — passing a positional
|
|
168
|
+
# hash to a keyword-only initializer raises ArgumentError. Rebuild
|
|
169
|
+
# with the keyword splat instead.
|
|
170
|
+
def exclude(*args)
|
|
171
|
+
excluded_args = args.dup
|
|
172
|
+
excluded_args << :date if excluded_args.delete(:year)
|
|
173
|
+
|
|
174
|
+
attrs = self.class.attributes.each_with_object({}) do |(name, _), h|
|
|
175
|
+
h[name] = excluded_args.include?(name) ? nil : public_send(name)
|
|
159
176
|
end
|
|
177
|
+
self.class.new(**attrs)
|
|
178
|
+
end
|
|
160
179
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
180
|
+
# Short-form supplement fragment ("sup", "sup1924", "supJan1924",
|
|
181
|
+
# "suprev", " supJun1925-Jun1926"), rendered from the structured
|
|
182
|
+
# component. A present-but-empty component is the bare "sup" marker; a
|
|
183
|
+
# number-less date range gets the leading space the number would have
|
|
184
|
+
# supplied. Shared by base and the per-series to_short_style overrides.
|
|
185
|
+
def supplement_short
|
|
186
|
+
return "" unless supplement
|
|
187
|
+
|
|
188
|
+
prefix = supplement.range? && !number ? " " : ""
|
|
189
|
+
rendered = supplement.to_s(:short)
|
|
190
|
+
prefix + (rendered.empty? ? "sup" : rendered)
|
|
191
|
+
end
|
|
173
192
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
193
|
+
# Compute revision from edition component for backward compatibility
|
|
194
|
+
# @return [String, nil] revision string (e.g., "r5") or nil
|
|
195
|
+
def revision
|
|
196
|
+
return @revision if @revision
|
|
178
197
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
end
|
|
198
|
+
# Compute from edition component if available
|
|
199
|
+
if edition&.type && edition.id
|
|
200
|
+
"#{edition.type}#{edition.id}"
|
|
183
201
|
end
|
|
202
|
+
end
|
|
184
203
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
204
|
+
# Backward compatibility: translation method returns translation_component
|
|
205
|
+
# This allows tests to use parsed.translation.language instead of parsed.translation_component.language
|
|
206
|
+
def translation
|
|
207
|
+
translation_component
|
|
208
|
+
end
|
|
190
209
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
210
|
+
# Backward compatibility: language method returns translation_component
|
|
211
|
+
# This allows tests to use parsed.language instead of parsed.translation_component
|
|
212
|
+
def language
|
|
213
|
+
translation_component
|
|
214
|
+
end
|
|
196
215
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
# Falls back to :short format for output (normalization)
|
|
205
|
-
# Explicit format parameter always overrides parsed_format
|
|
206
|
-
effective_format = format || parsed_format&.to_sym || :short
|
|
207
|
-
effective_format = effective_format.to_sym if effective_format.is_a?(String)
|
|
208
|
-
case effective_format
|
|
209
|
-
when :full, :long
|
|
210
|
-
to_full_style
|
|
211
|
-
when :abbreviated, :abbrev
|
|
212
|
-
to_abbreviated_style
|
|
213
|
-
when :short
|
|
214
|
-
to_short_style
|
|
215
|
-
when :mr
|
|
216
|
-
to_mr_style
|
|
217
|
-
else
|
|
218
|
-
to_short_style
|
|
219
|
-
end
|
|
216
|
+
# Override parent render to pass NIST-specific format option through
|
|
217
|
+
# to the renderer. Pubid::Identifier#render only forwards
|
|
218
|
+
# :with_edition; NIST needs :nist_format for multi-format support.
|
|
219
|
+
def render(format: :human, **opts)
|
|
220
|
+
registry = self.class.format_registry
|
|
221
|
+
unless registry
|
|
222
|
+
raise ArgumentError, "No format registry configured on #{self.class}"
|
|
220
223
|
end
|
|
221
224
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
def weight
|
|
226
|
-
self.class.attributes.keys.inject(0) do |sum, key|
|
|
227
|
-
val = public_send(key)
|
|
228
|
-
val && !val.to_s.empty? ? sum + 1 : sum
|
|
229
|
-
end
|
|
225
|
+
renderer = registry.renderer_for(format)
|
|
226
|
+
unless renderer
|
|
227
|
+
raise ArgumentError, "No renderer registered for format: #{format}"
|
|
230
228
|
end
|
|
231
229
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
# @param document [Base] another NIST document to merge
|
|
235
|
-
# @return [Base] self with merged attributes
|
|
236
|
-
def merge(document)
|
|
237
|
-
return self unless document.is_a?(Base)
|
|
238
|
-
|
|
239
|
-
attrs = self.class.attributes
|
|
240
|
-
attrs.each_key do |var_name|
|
|
241
|
-
next if var_name == :rendering_style
|
|
242
|
-
next if var_name == :parsed_format
|
|
243
|
-
|
|
244
|
-
current_val = public_send(var_name)
|
|
245
|
-
new_val = document.public_send(var_name)
|
|
246
|
-
next unless new_val
|
|
247
|
-
|
|
248
|
-
should_merge = case var_name
|
|
249
|
-
when :publisher, :series, :number
|
|
250
|
-
true
|
|
251
|
-
when :edition
|
|
252
|
-
current_val.nil? || edition_greater?(new_val,
|
|
253
|
-
current_val)
|
|
254
|
-
when :volume, :part, :version, :revision
|
|
255
|
-
current_val.nil? || (new_val.to_s.length > current_val.to_s.length)
|
|
256
|
-
when :supplement, :errata, :index, :insert, :section, :appendix, :translation
|
|
257
|
-
true
|
|
258
|
-
when :year, :month, :update, :draft
|
|
259
|
-
true
|
|
260
|
-
else
|
|
261
|
-
false
|
|
262
|
-
end
|
|
230
|
+
renderer.new(self).render(**opts)
|
|
231
|
+
end
|
|
263
232
|
|
|
264
|
-
|
|
265
|
-
|
|
233
|
+
# Generate identifier string in specified format
|
|
234
|
+
# @param format [:full, :long, :abbreviated, :short, :mr] output format
|
|
235
|
+
def to_s(format = nil)
|
|
236
|
+
# Handle both keyword argument (hash) and positional argument (symbol/string)
|
|
237
|
+
format = format[:format] if format.is_a?(Hash)
|
|
238
|
+
|
|
239
|
+
# Default to parsed_format if available (preserves input format on round-trip)
|
|
240
|
+
# Falls back to :short format for output (normalization)
|
|
241
|
+
# Explicit format parameter always overrides parsed_format
|
|
242
|
+
render(format: :human,
|
|
243
|
+
nist_format: format || parsed_format&.to_sym || :short)
|
|
244
|
+
end
|
|
266
245
|
|
|
267
|
-
|
|
246
|
+
# Returns weight based on amount of defined attributes
|
|
247
|
+
# Used for ranking identifiers by specificity for conflict resolution
|
|
248
|
+
# @return [Integer] weight score (higher = more specific)
|
|
249
|
+
def weight
|
|
250
|
+
self.class.attributes.keys.inject(0) do |sum, key|
|
|
251
|
+
val = public_send(key)
|
|
252
|
+
val && !val.to_s.empty? ? sum + 1 : sum
|
|
268
253
|
end
|
|
254
|
+
end
|
|
269
255
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
256
|
+
# Merge another document into this one
|
|
257
|
+
# Used for combining document data, preferring more specific values
|
|
258
|
+
# @param document [Base] another NIST document to merge
|
|
259
|
+
# @return [Base] self with merged attributes
|
|
260
|
+
def merge(document)
|
|
261
|
+
return self unless document.is_a?(Pubid::Nist::Identifier)
|
|
262
|
+
|
|
263
|
+
attrs = self.class.attributes
|
|
264
|
+
attrs.each_key do |var_name|
|
|
265
|
+
next if var_name == :rendering_style
|
|
266
|
+
next if var_name == :parsed_format
|
|
267
|
+
|
|
268
|
+
current_val = public_send(var_name)
|
|
269
|
+
new_val = document.public_send(var_name)
|
|
270
|
+
next unless new_val
|
|
271
|
+
|
|
272
|
+
should_merge = case var_name
|
|
273
|
+
when :publisher, :series, :number
|
|
274
|
+
true
|
|
275
|
+
when :edition
|
|
276
|
+
current_val.nil? || edition_greater?(new_val,
|
|
277
|
+
current_val)
|
|
278
|
+
when :volume, :part, :version, :revision
|
|
279
|
+
current_val.nil? || (new_val.to_s.length > current_val.to_s.length)
|
|
280
|
+
when :supplement, :errata, :index, :insert, :section, :appendix, :translation
|
|
281
|
+
true
|
|
282
|
+
when :year, :month, :update, :draft
|
|
283
|
+
true
|
|
284
|
+
else
|
|
285
|
+
false
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
public_send(:"#{var_name}=", new_val) if should_merge
|
|
276
289
|
end
|
|
277
290
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
291
|
+
self
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
# Helper to compare edition values numerically
|
|
295
|
+
# @return [Boolean] true if edition1 is greater than edition2
|
|
296
|
+
def edition_greater?(edition1, edition2)
|
|
297
|
+
num1 = extract_edition_number(edition1)
|
|
298
|
+
num2 = extract_edition_number(edition2)
|
|
299
|
+
num1 && num2 && num1 > num2
|
|
300
|
+
end
|
|
287
301
|
|
|
288
|
-
|
|
302
|
+
# Extract numeric value from edition (r3 -> 3, r5 -> 5, e2 -> 2)
|
|
303
|
+
# @return [Integer, nil] the edition number or nil if not extractable
|
|
304
|
+
def extract_edition_number(edition)
|
|
305
|
+
# Handle both String and Edition component
|
|
306
|
+
edition_str = edition.to_s
|
|
307
|
+
# Match patterns like r3, r5, e2, etc.
|
|
308
|
+
match = edition_str.match(/^[er]?(\d+)$/)
|
|
309
|
+
match ? match[1].to_i : nil
|
|
310
|
+
end
|
|
289
311
|
|
|
290
|
-
|
|
291
|
-
# "National Institute of Standards and Technology Special Publication 800-27, Revision A"
|
|
292
|
-
result = publisher_full_name
|
|
293
|
-
result += " #{series_full_name}" if series
|
|
294
|
-
result += " #{number.value}" if number
|
|
295
|
-
result += parts.map { |p| "-#{p}" }.join if parts&.any?
|
|
312
|
+
public
|
|
296
313
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
314
|
+
def to_full_style
|
|
315
|
+
# "National Institute of Standards and Technology Special Publication 800-27, Revision A"
|
|
316
|
+
result = publisher_full_name
|
|
317
|
+
result += " #{series_full_name}" if series
|
|
318
|
+
result += " #{number.value}" if number
|
|
319
|
+
result += parts.map { |p| "-#{p}" }.join if parts&.any?
|
|
303
320
|
|
|
304
|
-
|
|
305
|
-
|
|
321
|
+
# Render volume and issue number in long form: "Vol. 6, No. 12"
|
|
322
|
+
if volume && issue_number
|
|
323
|
+
result += " Vol. #{volume}, #{issue_number.to_s(:long)}"
|
|
324
|
+
elsif volume
|
|
325
|
+
result += " Vol. #{volume}"
|
|
326
|
+
end
|
|
306
327
|
|
|
307
|
-
|
|
328
|
+
# NEW: Use edition component properly
|
|
329
|
+
result += " #{edition.to_s(:long)}" if edition
|
|
308
330
|
|
|
309
|
-
|
|
310
|
-
result += " #{version_component.to_s(:long)}" if version_component
|
|
331
|
+
result += ", Revision #{revision.sub(/^r/, '')}" if revision
|
|
311
332
|
|
|
312
|
-
|
|
313
|
-
|
|
333
|
+
# V2: Use version_component
|
|
334
|
+
result += " #{version_component.to_s(:long)}" if version_component
|
|
314
335
|
|
|
315
|
-
|
|
316
|
-
|
|
336
|
+
# V2: Use update_component
|
|
337
|
+
result += " #{update_component.to_s(:long)}" if update_component
|
|
317
338
|
|
|
318
|
-
|
|
319
|
-
|
|
339
|
+
# V2: Use stage
|
|
340
|
+
result += " #{stage.to_s(:long)}" if stage
|
|
320
341
|
|
|
321
|
-
|
|
322
|
-
|
|
342
|
+
# V2: Use translation_component (already includes space)
|
|
343
|
+
result += translation_component.to_s(:long) if translation_component
|
|
344
|
+
|
|
345
|
+
result
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
def to_abbreviated_style
|
|
349
|
+
# "Natl. Inst. Stand. Technol. Spec. Publ. 800-57 Part 1, Revision 4"
|
|
350
|
+
result = publisher_abbreviated_name
|
|
351
|
+
result += " #{series_abbreviated_name}" if series
|
|
352
|
+
result += " #{number}" if number
|
|
353
|
+
result += " Part #{parts.first}" if parts&.any?
|
|
354
|
+
|
|
355
|
+
# NEW: Use edition component properly
|
|
356
|
+
result += " #{edition.to_s(:abbrev)}" if edition
|
|
323
357
|
|
|
324
|
-
|
|
325
|
-
# "Natl. Inst. Stand. Technol. Spec. Publ. 800-57 Part 1, Revision 4"
|
|
326
|
-
result = publisher_abbreviated_name
|
|
327
|
-
result += " #{series_abbreviated_name}" if series
|
|
328
|
-
result += " #{number}" if number
|
|
329
|
-
result += " Part #{parts.first}" if parts&.any?
|
|
358
|
+
result += ", Revision #{revision}" if revision
|
|
330
359
|
|
|
331
|
-
|
|
332
|
-
|
|
360
|
+
# V2: Use version_component
|
|
361
|
+
result += " #{version_component.to_s(:abbrev)}" if version_component
|
|
333
362
|
|
|
334
|
-
|
|
363
|
+
# V2: Use update_component
|
|
364
|
+
result += " #{update_component.to_s(:abbrev)}" if update_component
|
|
335
365
|
|
|
336
|
-
|
|
337
|
-
|
|
366
|
+
# V2: Use stage
|
|
367
|
+
result += " #{stage.to_s(:abbrev)}" if stage
|
|
338
368
|
|
|
339
|
-
|
|
340
|
-
|
|
369
|
+
# V2: Use translation_component
|
|
370
|
+
result += ", #{translation_component.to_s(:abbrev)}" if translation_component
|
|
341
371
|
|
|
342
|
-
|
|
343
|
-
|
|
372
|
+
result
|
|
373
|
+
end
|
|
344
374
|
|
|
345
|
-
|
|
346
|
-
|
|
375
|
+
def to_short_style
|
|
376
|
+
# "SP 800-187" or "NIST SP 800-187" - handle compound series properly
|
|
377
|
+
result = ""
|
|
378
|
+
|
|
379
|
+
# Determine effective publisher
|
|
380
|
+
# Only show publisher if it was explicitly parsed (either directly or from series prefix)
|
|
381
|
+
effective_publisher = if publisher && publisher_was_parsed
|
|
382
|
+
# Publisher was in input (either as separate field or extracted from "NBS CS" series)
|
|
383
|
+
publisher.to_s
|
|
384
|
+
else
|
|
385
|
+
# No publisher in input, don't show default
|
|
386
|
+
nil
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
# Determine effective series - PREFER series_code if subclass defines it
|
|
390
|
+
# This allows normalization (e.g., LCIRC → LC in LetterCircular)
|
|
391
|
+
effective_series = if series_code
|
|
392
|
+
series_code
|
|
393
|
+
elsif series
|
|
394
|
+
series.to_s
|
|
395
|
+
end
|
|
347
396
|
|
|
348
|
-
|
|
397
|
+
# Special handling for compound series that include publisher prefix
|
|
398
|
+
# If series starts with "NBS " (like "NBS CIRC"), use it as-is
|
|
399
|
+
if effective_series&.start_with?("NBS ")
|
|
400
|
+
result += effective_series
|
|
401
|
+
elsif effective_publisher && effective_series
|
|
402
|
+
result += "#{effective_publisher} #{effective_series}"
|
|
403
|
+
elsif effective_series && publisher_was_parsed
|
|
404
|
+
# Only add "NIST" prefix if publisher was explicitly in the input
|
|
405
|
+
result += "NIST #{effective_series}"
|
|
406
|
+
elsif effective_series
|
|
407
|
+
# No publisher in input, just show series without prefix
|
|
408
|
+
result += effective_series
|
|
349
409
|
end
|
|
350
410
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
result = ""
|
|
354
|
-
|
|
355
|
-
# Determine effective publisher
|
|
356
|
-
# Only show publisher if it was explicitly parsed (either directly or from series prefix)
|
|
357
|
-
effective_publisher = if publisher && publisher_was_parsed
|
|
358
|
-
# Publisher was in input (either as separate field or extracted from "NBS CS" series)
|
|
359
|
-
publisher.to_s
|
|
360
|
-
else
|
|
361
|
-
# No publisher in input, don't show default
|
|
362
|
-
nil
|
|
363
|
-
end
|
|
364
|
-
|
|
365
|
-
# Determine effective series - PREFER series_code if subclass defines it
|
|
366
|
-
# This allows normalization (e.g., LCIRC → LC in LetterCircular)
|
|
367
|
-
effective_series = if series_code
|
|
368
|
-
series_code
|
|
369
|
-
elsif series
|
|
370
|
-
series.to_s
|
|
371
|
-
end
|
|
372
|
-
|
|
373
|
-
# Special handling for compound series that include publisher prefix
|
|
374
|
-
# If series starts with "NBS " (like "NBS CIRC"), use it as-is
|
|
375
|
-
if effective_series&.start_with?("NBS ")
|
|
376
|
-
result += effective_series
|
|
377
|
-
elsif effective_publisher && effective_series
|
|
378
|
-
result += "#{effective_publisher} #{effective_series}"
|
|
379
|
-
elsif effective_series && publisher_was_parsed
|
|
380
|
-
# Only add "NIST" prefix if publisher was explicitly in the input
|
|
381
|
-
result += "NIST #{effective_series}"
|
|
382
|
-
elsif effective_series
|
|
383
|
-
# No publisher in input, just show series without prefix
|
|
384
|
-
result += effective_series
|
|
385
|
-
end
|
|
411
|
+
result += " #{number}" if number
|
|
412
|
+
result += parts.map { |p| "-#{p}" }.join if parts&.any?
|
|
386
413
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
# CSM series: v#n# notation
|
|
393
|
-
result += " #{volume}#{part}"
|
|
394
|
-
elsif part.is_a?(Components::Part)
|
|
395
|
-
# SP and other series: use Part.type to determine format
|
|
396
|
-
result += part.to_s
|
|
397
|
-
# Legacy: Render standalone volume (not part of v#n#)
|
|
398
|
-
elsif volume && !issue_number && !part
|
|
399
|
-
vol_str = volume.is_a?(Components::Volume) ? volume.to_s : "v#{volume}"
|
|
400
|
-
result += vol_str
|
|
401
|
-
elsif volume && issue_number
|
|
402
|
-
# Render volume and issue number in short form: "v6n12"
|
|
403
|
-
vol_str = volume.is_a?(Components::Volume) ? volume.to_s : "v#{volume}"
|
|
404
|
-
result += "#{vol_str}n#{issue_number.number}"
|
|
405
|
-
end
|
|
414
|
+
# Append every optional component the parser may have attached
|
|
415
|
+
# (volume, part, edition, version, supplement, update, stage, ...).
|
|
416
|
+
# Shared with the lossy subclasses so they cannot silently drop a
|
|
417
|
+
# distinguishing component and collide with another document.
|
|
418
|
+
result += append_short_components
|
|
406
419
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
# Only add space for bare edition (no number case) or if original_prefix has specific format
|
|
410
|
-
if edition
|
|
411
|
-
if edition.original_prefix && !edition.original_prefix.empty?
|
|
412
|
-
# original_prefix includes the full prefix (e.g., " Rev. " for verbose format)
|
|
413
|
-
result += edition.to_s
|
|
414
|
-
elsif number
|
|
415
|
-
# Number present, NO space: "800-53r5"
|
|
416
|
-
result += edition.to_s
|
|
417
|
-
else
|
|
418
|
-
# Bare edition, add space: " r5"
|
|
419
|
-
result += " #{edition}"
|
|
420
|
-
end
|
|
421
|
-
end
|
|
420
|
+
result
|
|
421
|
+
end
|
|
422
422
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
423
|
+
# Render the optional component "tail" that follows
|
|
424
|
+
# publisher/series/number in short (human) form. Extracted from
|
|
425
|
+
# #to_short_style so subclasses that build a series-specific prefix can
|
|
426
|
+
# reuse it instead of hand-listing components (and forgetting some).
|
|
427
|
+
#
|
|
428
|
+
# skip_part: true lets a series that renders its part differently
|
|
429
|
+
# (e.g. FIPS uses dash "-1", not "pt1") emit the part itself and skip
|
|
430
|
+
# the generic part rendering here, while still getting volume/edition/
|
|
431
|
+
# supplement/etc.
|
|
432
|
+
def append_short_components(skip_part: false)
|
|
433
|
+
result = ""
|
|
434
|
+
effective_part = skip_part ? nil : part
|
|
435
|
+
|
|
436
|
+
# Volume and Part components (v6n1 notation for CSM, pt1 for SP)
|
|
437
|
+
if volume.is_a?(Components::Volume) && effective_part.is_a?(Components::Part)
|
|
438
|
+
# CSM series: v#n# notation
|
|
439
|
+
result += " #{volume}#{effective_part}"
|
|
440
|
+
elsif effective_part.is_a?(Components::Part)
|
|
441
|
+
# SP and other series: use Part.type to determine format
|
|
442
|
+
result += effective_part.to_s
|
|
443
|
+
# Legacy: Render standalone volume (not part of v#n#)
|
|
444
|
+
elsif volume && !issue_number && !effective_part
|
|
445
|
+
vol_str = volume.is_a?(Components::Volume) ? volume.to_s : "v#{volume}"
|
|
446
|
+
result += vol_str
|
|
447
|
+
elsif volume && issue_number
|
|
448
|
+
# Render volume and issue number in short form: "v6n12"
|
|
449
|
+
vol_str = volume.is_a?(Components::Volume) ? volume.to_s : "v#{volume}"
|
|
450
|
+
result += "#{vol_str}n#{issue_number.number}"
|
|
451
|
+
end
|
|
432
452
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
# Add addendum - render as " Add." suffix
|
|
448
|
-
if addendum || addendum_number
|
|
449
|
-
result += " Add."
|
|
453
|
+
# Use edition component properly (e2, e2021, r5, -3)
|
|
454
|
+
# NO space before edition when number present (per NIST spec)
|
|
455
|
+
# Only add space for bare edition (no number case) or if original_prefix has specific format
|
|
456
|
+
if edition
|
|
457
|
+
if edition.original_prefix && !edition.original_prefix.empty?
|
|
458
|
+
# original_prefix includes the full prefix (e.g., " Rev. " for verbose format)
|
|
459
|
+
result += edition.to_s
|
|
460
|
+
elsif number
|
|
461
|
+
# Number present, NO space: "800-53r5"
|
|
462
|
+
result += edition.to_s
|
|
463
|
+
else
|
|
464
|
+
# Bare edition, add space: " r5"
|
|
465
|
+
result += " #{edition}"
|
|
450
466
|
end
|
|
467
|
+
end
|
|
451
468
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
469
|
+
# Use version_component if available, else use version string.
|
|
470
|
+
# Attach directly (no leading space) to match edition rendering
|
|
471
|
+
# (e.g. "800-53r5"), so version reads "800-45ver2" not
|
|
472
|
+
# "800-45 ver2".
|
|
473
|
+
if version_component
|
|
474
|
+
result += version_component.to_s(:short)
|
|
475
|
+
elsif version
|
|
476
|
+
result += "ver#{version}"
|
|
477
|
+
end
|
|
458
478
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
479
|
+
# Add supplement. NIST/NBS canonical short form is single-p "sup"
|
|
480
|
+
# with the suffix attached directly, no dash (relaton-data-nist
|
|
481
|
+
# uses "sup2", "sup1940", "supA"); date-range keeps its inner dash.
|
|
482
|
+
# Rendered from the structured component; a present-but-empty
|
|
483
|
+
# component is the bare "sup" marker.
|
|
484
|
+
result += supplement_short
|
|
485
|
+
|
|
486
|
+
# Add other attributes
|
|
487
|
+
result += errata.to_s if errata
|
|
488
|
+
result += "index" if index
|
|
489
|
+
result += "insert" if insert
|
|
490
|
+
result += "sec#{section}" if section
|
|
491
|
+
result += "app" if appendix
|
|
492
|
+
|
|
493
|
+
# Add addendum - render as " Add." suffix
|
|
494
|
+
if addendum || addendum_number
|
|
495
|
+
result += " Add."
|
|
496
|
+
end
|
|
465
497
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
498
|
+
# Use update_component if available, else use update string
|
|
499
|
+
if update_component
|
|
500
|
+
result += update_component.to_s(:short)
|
|
501
|
+
elsif update
|
|
502
|
+
result += "-upd#{update}"
|
|
503
|
+
end
|
|
470
504
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
end
|
|
505
|
+
# Add draft - render as {N}pd if draft_number present
|
|
506
|
+
if draft_number
|
|
507
|
+
result += " #{draft_number}pd"
|
|
508
|
+
elsif draft&.to_s&.include?("draft") && !draft.to_s.include?("Draft)")
|
|
509
|
+
result += "-draft"
|
|
510
|
+
end
|
|
478
511
|
|
|
479
|
-
|
|
512
|
+
# Add stage component (at end, before translation)
|
|
513
|
+
if stage
|
|
514
|
+
result += " #{stage.to_s(:short)}"
|
|
480
515
|
end
|
|
481
516
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
series_code
|
|
490
|
-
elsif series
|
|
491
|
-
series.to_s
|
|
492
|
-
end
|
|
493
|
-
|
|
494
|
-
result += ".#{effective_series}" if effective_series
|
|
495
|
-
result += ".#{number}" if number
|
|
496
|
-
result += parts.map { |p| "-#{p}" }.join if parts&.any?
|
|
497
|
-
|
|
498
|
-
# Part component (pt1, v6n1, etc.)
|
|
499
|
-
result += part.to_s if part.is_a?(Components::Part)
|
|
500
|
-
|
|
501
|
-
# NEW: Use edition component - NO space before edition in MR format (per NIST spec)
|
|
502
|
-
if edition
|
|
503
|
-
# If edition has original_prefix set (e.g., verbose " Rev. "), use it as-is
|
|
504
|
-
# Otherwise, no space needed in MR format: ".800-53r5"
|
|
505
|
-
if edition.original_prefix && !edition.original_prefix.empty?
|
|
506
|
-
end
|
|
507
|
-
result += edition.to_s
|
|
508
|
-
end
|
|
517
|
+
# Use translation_component if available, else use translation string
|
|
518
|
+
# Note: translation_component.to_s already includes the space prefix
|
|
519
|
+
if translation_component
|
|
520
|
+
result += translation_component.to_s(:short)
|
|
521
|
+
elsif translation
|
|
522
|
+
result += " #{translation}"
|
|
523
|
+
end
|
|
509
524
|
|
|
510
|
-
|
|
511
|
-
|
|
525
|
+
result
|
|
526
|
+
end
|
|
512
527
|
|
|
513
|
-
|
|
514
|
-
|
|
528
|
+
def to_mr_style
|
|
529
|
+
# "NIST.SP.800-116r1.ipd" (machine-readable with dots)
|
|
530
|
+
result = (publisher || "NIST").to_s
|
|
515
531
|
|
|
516
|
-
|
|
517
|
-
|
|
532
|
+
# Determine effective series - PREFER series_code if subclass defines it
|
|
533
|
+
# This allows normalization (e.g., LCIRC → LC in LetterCircular)
|
|
534
|
+
effective_series = if series_code
|
|
535
|
+
series_code
|
|
536
|
+
elsif series
|
|
537
|
+
series.to_s
|
|
538
|
+
end
|
|
518
539
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
end
|
|
540
|
+
result += ".#{effective_series}" if effective_series
|
|
541
|
+
result += ".#{number}" if number
|
|
542
|
+
result += parts.map { |p| "-#{p}" }.join if parts&.any?
|
|
523
543
|
|
|
524
|
-
|
|
525
|
-
result += translation_component.to_s(:mr) if translation_component
|
|
544
|
+
result += append_mr_components
|
|
526
545
|
|
|
527
|
-
|
|
528
|
-
|
|
546
|
+
result
|
|
547
|
+
end
|
|
529
548
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
549
|
+
# Render the optional component tail for machine-readable (MR) form.
|
|
550
|
+
# Mirrors #append_short_components so the MR output is just as lossless;
|
|
551
|
+
# subclasses that override #to_mr_style reuse this instead of
|
|
552
|
+
# hand-listing components. skip_part: behaves as in the short helper.
|
|
553
|
+
def append_mr_components(skip_part: false)
|
|
554
|
+
result = ""
|
|
555
|
+
effective_part = skip_part ? nil : part
|
|
556
|
+
|
|
557
|
+
# Volume / Part components (pt1, v6n1, etc.)
|
|
558
|
+
if volume.is_a?(Components::Volume) && effective_part.is_a?(Components::Part)
|
|
559
|
+
result += "#{volume}#{effective_part}"
|
|
560
|
+
elsif effective_part.is_a?(Components::Part)
|
|
561
|
+
result += effective_part.to_s
|
|
562
|
+
elsif volume && !issue_number && !effective_part
|
|
563
|
+
result += (volume.is_a?(Components::Volume) ? volume.to_s : "v#{volume}")
|
|
564
|
+
elsif volume && issue_number
|
|
565
|
+
vol_str = volume.is_a?(Components::Volume) ? volume.to_s : "v#{volume}"
|
|
566
|
+
result += "#{vol_str}n#{issue_number.number}"
|
|
537
567
|
end
|
|
538
568
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
"SP" => "Spec. Publ.",
|
|
542
|
-
"FIPS" => "Fed. Inf. Proc. Stand.",
|
|
543
|
-
"IR" => "Interag. Rep.",
|
|
544
|
-
"TN" => "Tech. Note",
|
|
545
|
-
}[series&.to_s || series_code] || (series&.to_s || series_code)
|
|
546
|
-
end
|
|
569
|
+
# Use edition component - NO space before edition in MR format (per NIST spec)
|
|
570
|
+
result += edition.to_s if edition
|
|
547
571
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
572
|
+
# Use version_component
|
|
573
|
+
result += version_component.to_s(:mr) if version_component
|
|
574
|
+
|
|
575
|
+
# Supplement (e.g. ".9981sup7") - keep distinct documents distinct
|
|
576
|
+
result += supplement_short
|
|
577
|
+
|
|
578
|
+
# Use update_component
|
|
579
|
+
result += update_component.to_s(:mr) if update_component
|
|
580
|
+
|
|
581
|
+
# Use stage
|
|
582
|
+
result += ".#{stage.to_s(:mr)}" if stage
|
|
583
|
+
|
|
584
|
+
# Add addendum - render as ".Add." suffix in MR format
|
|
585
|
+
if addendum || addendum_number
|
|
586
|
+
result += ".Add."
|
|
557
587
|
end
|
|
558
588
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
589
|
+
# Use translation_component
|
|
590
|
+
result += translation_component.to_s(:mr) if translation_component
|
|
591
|
+
|
|
592
|
+
result
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
def series_full_name
|
|
596
|
+
{
|
|
597
|
+
"SP" => "Special Publication",
|
|
598
|
+
"FIPS" => "Federal Information Processing Standards",
|
|
599
|
+
"IR" => "Interagency Report",
|
|
600
|
+
"TN" => "Technical Note",
|
|
601
|
+
}[series] || series
|
|
602
|
+
end
|
|
603
|
+
|
|
604
|
+
def series_abbreviated_name
|
|
605
|
+
{
|
|
606
|
+
"SP" => "Spec. Publ.",
|
|
607
|
+
"FIPS" => "Fed. Inf. Proc. Stand.",
|
|
608
|
+
"IR" => "Interag. Rep.",
|
|
609
|
+
"TN" => "Tech. Note",
|
|
610
|
+
}[series&.to_s || series_code] || (series&.to_s || series_code)
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
def publisher_full_name
|
|
614
|
+
case publisher.to_s
|
|
615
|
+
when "NBS"
|
|
616
|
+
"National Bureau of Standards"
|
|
617
|
+
when "NIST"
|
|
618
|
+
"National Institute of Standards and Technology"
|
|
619
|
+
else
|
|
620
|
+
publisher.to_s
|
|
568
621
|
end
|
|
622
|
+
end
|
|
569
623
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
"
|
|
624
|
+
def publisher_abbreviated_name
|
|
625
|
+
case publisher.to_s
|
|
626
|
+
when "NBS"
|
|
627
|
+
"Natl. Bur. Stand."
|
|
628
|
+
when "NIST"
|
|
629
|
+
"Natl. Inst. Stand. Technol."
|
|
630
|
+
else
|
|
631
|
+
publisher.to_s
|
|
574
632
|
end
|
|
575
633
|
end
|
|
634
|
+
|
|
635
|
+
# Default publisher for series without explicit publisher
|
|
636
|
+
# Subclasses can override
|
|
637
|
+
def default_publisher
|
|
638
|
+
"NIST"
|
|
639
|
+
end
|
|
640
|
+
end
|
|
641
|
+
|
|
642
|
+
module Identifiers
|
|
643
|
+
# Backward-compatible alias: NIST's base class used to be
|
|
644
|
+
# Pubid::Nist::Identifiers::Base. It is now Pubid::Nist::Identifier; keep
|
|
645
|
+
# the old constant working for `class Foo < Base` declarations and any
|
|
646
|
+
# external reference.
|
|
647
|
+
Base = Pubid::Nist::Identifier
|
|
576
648
|
end
|
|
577
649
|
end
|
|
578
650
|
end
|