pubid 2.0.0.pre.alpha.9 → 2.0.0.pre.alpha.11
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 +33 -11
- data/conformance/pending.yaml +4 -0
- data/lib/pubid/adobe/identifier.rb +1 -3
- data/lib/pubid/adobe/parser.rb +10 -2
- data/lib/pubid/adobe.rb +1 -0
- data/lib/pubid/amca/builder.rb +2 -2
- data/lib/pubid/amca/identifiers/base.rb +49 -27
- data/lib/pubid/amca/identifiers/interpretation.rb +17 -9
- data/lib/pubid/amca/identifiers/publication.rb +13 -9
- data/lib/pubid/amca/identifiers/standard.rb +2 -0
- data/lib/pubid/amca/parser.rb +1 -1
- data/lib/pubid/amca/renderer.rb +4 -4
- data/lib/pubid/amca/urn_generator.rb +2 -2
- data/lib/pubid/amca.rb +2 -1
- data/lib/pubid/ansi/builder.rb +2 -2
- data/lib/pubid/ansi/identifier.rb +18 -0
- data/lib/pubid/ansi/parser.rb +1 -1
- data/lib/pubid/ansi/renderer.rb +2 -2
- data/lib/pubid/ansi.rb +5 -5
- data/lib/pubid/api/builder.rb +16 -2
- data/lib/pubid/api/identifier.rb +25 -4
- data/lib/pubid/api/identifiers/mpms.rb +10 -8
- data/lib/pubid/api/parser.rb +1 -1
- data/lib/pubid/api/renderer.rb +16 -7
- data/lib/pubid/api/single_identifier.rb +5 -12
- data/lib/pubid/api.rb +1 -0
- data/lib/pubid/ashrae/builder.rb +31 -10
- data/lib/pubid/ashrae/identifiers/addenda_package.rb +6 -0
- data/lib/pubid/ashrae/identifiers/addendum.rb +8 -0
- data/lib/pubid/ashrae/identifiers/base.rb +81 -5
- data/lib/pubid/ashrae/identifiers/combined_addenda.rb +7 -0
- data/lib/pubid/ashrae/identifiers/errata.rb +9 -0
- data/lib/pubid/ashrae/identifiers/guideline.rb +3 -0
- data/lib/pubid/ashrae/identifiers/interpretation.rb +16 -0
- data/lib/pubid/ashrae/identifiers/standard.rb +3 -0
- data/lib/pubid/ashrae/parser.rb +23 -8
- data/lib/pubid/ashrae/renderer.rb +6 -6
- data/lib/pubid/ashrae/supplement_identifier.rb +17 -2
- data/lib/pubid/ashrae/urn_generator.rb +8 -2
- data/lib/pubid/ashrae.rb +7 -1
- data/lib/pubid/asme/builder.rb +11 -2
- data/lib/pubid/asme/identifier.rb +9 -0
- data/lib/pubid/asme/identifiers/standard.rb +86 -2
- data/lib/pubid/asme/parser.rb +1 -1
- data/lib/pubid/asme/renderer.rb +3 -3
- data/lib/pubid/asme/single_identifier.rb +8 -1
- data/lib/pubid/asme/urn_generator.rb +2 -2
- data/lib/pubid/asme.rb +1 -0
- data/lib/pubid/astm/builder.rb +10 -3
- data/lib/pubid/astm/identifier.rb +9 -0
- data/lib/pubid/astm/identifiers/adjunct.rb +16 -1
- data/lib/pubid/astm/identifiers/code_number.rb +81 -0
- data/lib/pubid/astm/identifiers/data_series.rb +2 -0
- data/lib/pubid/astm/identifiers/iso_dual_published.rb +16 -0
- data/lib/pubid/astm/identifiers/manual.rb +10 -0
- data/lib/pubid/astm/identifiers/monograph.rb +2 -0
- data/lib/pubid/astm/identifiers/research_report.rb +10 -0
- data/lib/pubid/astm/identifiers/standard.rb +10 -0
- data/lib/pubid/astm/identifiers/technical_report.rb +2 -0
- data/lib/pubid/astm/identifiers/work_in_progress.rb +2 -0
- data/lib/pubid/astm/identifiers.rb +1 -0
- data/lib/pubid/astm/parser.rb +1 -1
- data/lib/pubid/astm/renderer.rb +1 -1
- data/lib/pubid/astm/single_identifier.rb +31 -1
- data/lib/pubid/astm/urn_generator.rb +7 -5
- data/lib/pubid/astm.rb +1 -0
- data/lib/pubid/bipm/builder.rb +66 -10
- data/lib/pubid/bipm/identifier.rb +134 -9
- data/lib/pubid/bipm/identifiers/committee_document.rb +12 -0
- data/lib/pubid/bipm/identifiers/guide.rb +11 -0
- data/lib/pubid/bipm/identifiers/meeting.rb +12 -0
- data/lib/pubid/bipm/identifiers/mep.rb +12 -0
- data/lib/pubid/bipm/identifiers/metrologia_article.rb +24 -0
- data/lib/pubid/bipm/identifiers/si_brochure.rb +13 -0
- data/lib/pubid/bipm/parser.rb +65 -12
- data/lib/pubid/bipm/renderer.rb +8 -0
- data/lib/pubid/bipm/urn_parser.rb +11 -3
- data/lib/pubid/bipm.rb +7 -1
- data/lib/pubid/bsi/builder.rb +48 -38
- data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +36 -7
- data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +7 -6
- data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +0 -1
- data/lib/pubid/bsi/identifiers/bundled_identifier.rb +10 -0
- data/lib/pubid/bsi/identifiers/committee_document.rb +10 -1
- data/lib/pubid/bsi/identifiers/handbook.rb +0 -2
- data/lib/pubid/bsi/identifiers/practice_guide.rb +0 -1
- data/lib/pubid/bsi/identifiers/set.rb +11 -0
- data/lib/pubid/bsi/identifiers/standalone_amendment.rb +10 -1
- data/lib/pubid/bsi/parser.rb +1 -1
- data/lib/pubid/bsi/renderer.rb +63 -51
- data/lib/pubid/bsi/single_identifier.rb +16 -7
- data/lib/pubid/bsi/urn_generator.rb +11 -2
- data/lib/pubid/bsi.rb +7 -1
- data/lib/pubid/builder/base.rb +18 -8
- data/lib/pubid/bundled_identifier.rb +16 -6
- data/lib/pubid/calconnect/identifier.rb +9 -5
- data/lib/pubid/calconnect/parser.rb +1 -1
- data/lib/pubid/calconnect.rb +7 -1
- data/lib/pubid/ccsds/identifier.rb +9 -2
- data/lib/pubid/ccsds/identifiers/base.rb +4 -2
- data/lib/pubid/ccsds/identifiers/corrigendum.rb +2 -2
- data/lib/pubid/ccsds/parser.rb +1 -1
- data/lib/pubid/ccsds/single_identifier.rb +2 -2
- data/lib/pubid/ccsds.rb +1 -0
- data/lib/pubid/cen_cenelec/builder.rb +101 -76
- data/lib/pubid/cen_cenelec/identifier.rb +115 -3
- data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +27 -16
- data/lib/pubid/cen_cenelec/identifiers/amendment.rb +46 -6
- data/lib/pubid/cen_cenelec/identifiers/base.rb +8 -9
- data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/cenelec_harmonization_document.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +29 -20
- data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +47 -8
- data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +27 -2
- data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/fragment.rb +15 -5
- data/lib/pubid/cen_cenelec/identifiers/guide.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +1 -1
- data/lib/pubid/cen_cenelec/parser.rb +1 -1
- data/lib/pubid/cen_cenelec/renderer.rb +55 -60
- data/lib/pubid/cen_cenelec/single_identifier.rb +20 -2
- data/lib/pubid/cen_cenelec/urn_generator.rb +66 -44
- data/lib/pubid/cen_cenelec.rb +28 -10
- data/lib/pubid/cie/builder.rb +10 -0
- data/lib/pubid/cie/identifier.rb +6 -1
- data/lib/pubid/cie/identifiers/bundle.rb +4 -2
- data/lib/pubid/cie/identifiers/conference.rb +2 -2
- data/lib/pubid/cie/identifiers/corrigendum.rb +2 -2
- data/lib/pubid/cie/identifiers/dual_published.rb +2 -2
- data/lib/pubid/cie/identifiers/identical.rb +2 -2
- data/lib/pubid/cie/identifiers/joint_published.rb +2 -2
- data/lib/pubid/cie/identifiers/proceedings.rb +8 -6
- data/lib/pubid/cie/identifiers/standard.rb +22 -13
- data/lib/pubid/cie/identifiers/supplement.rb +2 -2
- data/lib/pubid/cie/identifiers/tutorial_bundle.rb +2 -2
- data/lib/pubid/cie/parser.rb +1 -1
- data/lib/pubid/cie.rb +7 -1
- data/lib/pubid/conformance/checks.rb +72 -0
- data/lib/pubid/conformance/corpus/case.rb +55 -0
- data/lib/pubid/conformance/corpus.rb +36 -0
- data/lib/pubid/conformance/generator.rb +212 -0
- data/lib/pubid/conformance/pending.rb +63 -0
- data/lib/pubid/conformance/runner.rb +153 -0
- data/lib/pubid/conformance.rb +55 -0
- data/lib/pubid/core.rb +2 -0
- data/lib/pubid/csa/builder.rb +47 -47
- data/lib/pubid/csa/composite_identifier.rb +14 -19
- data/lib/pubid/csa/identifier.rb +143 -81
- data/lib/pubid/csa/identifiers/bundled.rb +23 -13
- data/lib/pubid/csa/identifiers/canadian_adopted.rb +13 -13
- data/lib/pubid/csa/identifiers/cec.rb +44 -4
- data/lib/pubid/csa/identifiers/combined.rb +95 -73
- data/lib/pubid/csa/identifiers/csa_adopted.rb +4 -4
- data/lib/pubid/csa/identifiers/package.rb +2 -2
- data/lib/pubid/csa/parser.rb +6 -2
- data/lib/pubid/csa/renderer.rb +13 -5
- data/lib/pubid/csa/single_identifier.rb +93 -4
- data/lib/pubid/csa/urn_generator.rb +9 -2
- data/lib/pubid/csa/wrapper_identifier.rb +39 -23
- data/lib/pubid/csa.rb +7 -1
- data/lib/pubid/doi/identifier.rb +6 -3
- data/lib/pubid/doi/parser.rb +1 -1
- data/lib/pubid/doi.rb +1 -0
- data/lib/pubid/easc/identifier.rb +0 -2
- data/lib/pubid/easc/parser.rb +10 -2
- data/lib/pubid/easc.rb +1 -0
- data/lib/pubid/ecma/builder.rb +23 -9
- data/lib/pubid/ecma/identifier.rb +81 -10
- data/lib/pubid/ecma/parser.rb +39 -4
- data/lib/pubid/ecma/renderer.rb +29 -8
- data/lib/pubid/ecma/urn_generator.rb +34 -13
- data/lib/pubid/ecma/urn_parser.rb +30 -14
- data/lib/pubid/ecma.rb +1 -0
- data/lib/pubid/errors.rb +80 -0
- data/lib/pubid/etsi/builder.rb +6 -1
- data/lib/pubid/etsi/identifiers/base.rb +34 -20
- data/lib/pubid/etsi/identifiers/etsi_standard.rb +120 -41
- data/lib/pubid/etsi/identifiers/supplement_identifier.rb +10 -0
- data/lib/pubid/etsi/parser.rb +1 -1
- data/lib/pubid/etsi.rb +1 -0
- data/lib/pubid/evs/builder.rb +26 -0
- data/lib/pubid/evs/identifier.rb +37 -0
- data/lib/pubid/evs/identifiers/national_adoption.rb +17 -0
- data/lib/pubid/evs/identifiers.rb +9 -0
- data/lib/pubid/evs/parser.rb +27 -0
- data/lib/pubid/evs/renderer.rb +30 -0
- data/lib/pubid/evs/urn_generator.rb +30 -0
- data/lib/pubid/evs/urn_parser.rb +80 -0
- data/lib/pubid/evs.rb +90 -0
- data/lib/pubid/export.rb +1 -0
- data/lib/pubid/format_detector.rb +1 -0
- data/lib/pubid/gb/identifier.rb +6 -3
- data/lib/pubid/gb/parser.rb +1 -1
- data/lib/pubid/gb.rb +1 -0
- data/lib/pubid/gost/builder.rb +46 -9
- data/lib/pubid/gost/identifier.rb +0 -2
- data/lib/pubid/gost/identifiers/foreign_reference.rb +1 -1
- data/lib/pubid/gost/parser.rb +10 -2
- data/lib/pubid/gost.rb +1 -0
- data/lib/pubid/iala/identifier.rb +9 -6
- data/lib/pubid/iala/parser.rb +10 -2
- data/lib/pubid/iala/urn_parser.rb +6 -2
- data/lib/pubid/iala.rb +1 -0
- data/lib/pubid/iana/builder.rb +3 -1
- data/lib/pubid/iana/identifier.rb +74 -6
- data/lib/pubid/iana/identifiers/registry.rb +36 -0
- data/lib/pubid/iana/parser.rb +1 -1
- data/lib/pubid/iana/renderer.rb +3 -0
- data/lib/pubid/iana/urn_generator.rb +5 -1
- data/lib/pubid/iana.rb +1 -0
- data/lib/pubid/identifier.rb +594 -10
- data/lib/pubid/identifier_metadata.rb +1 -0
- data/lib/pubid/idf/builder.rb +3 -3
- data/lib/pubid/idf/identifier.rb +18 -9
- data/lib/pubid/idf/parser.rb +1 -1
- data/lib/pubid/idf/renderer.rb +4 -4
- data/lib/pubid/idf/urn_generator.rb +1 -1
- data/lib/pubid/idf.rb +7 -1
- data/lib/pubid/iec/builder.rb +14 -7
- data/lib/pubid/iec/components.rb +0 -1
- data/lib/pubid/iec/identifier.rb +73 -83
- data/lib/pubid/iec/identifiers/amendment.rb +6 -2
- data/lib/pubid/iec/identifiers/component_specification.rb +0 -10
- data/lib/pubid/iec/identifiers/conformity_assessment.rb +0 -10
- data/lib/pubid/iec/identifiers/corrigendum.rb +2 -2
- data/lib/pubid/iec/identifiers/fragment_identifier.rb +2 -4
- data/lib/pubid/iec/identifiers/guide.rb +0 -16
- data/lib/pubid/iec/identifiers/international_standard.rb +15 -2
- data/lib/pubid/iec/identifiers/operational_document.rb +0 -10
- data/lib/pubid/iec/identifiers/publicly_available_specification.rb +0 -12
- data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +0 -10
- data/lib/pubid/iec/identifiers/systems_reference_document.rb +0 -10
- data/lib/pubid/iec/identifiers/technical_report.rb +0 -17
- data/lib/pubid/iec/identifiers/technical_specification.rb +0 -17
- data/lib/pubid/iec/identifiers/technology_report.rb +0 -10
- data/lib/pubid/iec/identifiers/test_report_form.rb +0 -11
- data/lib/pubid/iec/identifiers/white_paper.rb +0 -10
- data/lib/pubid/iec/identifiers/working_document.rb +24 -10
- data/lib/pubid/iec/parser.rb +2 -18
- data/lib/pubid/iec/renderer.rb +13 -10
- data/lib/pubid/iec/single_identifier.rb +33 -10
- data/lib/pubid/iec/urn_generator.rb +227 -61
- data/lib/pubid/iec/urn_parser.rb +42 -4
- data/lib/pubid/iec.rb +1 -0
- data/lib/pubid/ieee/aiee/identifier.rb +2 -2
- data/lib/pubid/ieee/aiee/parser.rb +1 -1
- data/lib/pubid/ieee/builder.rb +45 -1
- data/lib/pubid/ieee/identifiers/adopted_standard.rb +32 -0
- data/lib/pubid/ieee/identifiers/base.rb +42 -5
- data/lib/pubid/ieee/identifiers/csa_dual_published.rb +21 -0
- data/lib/pubid/ieee/identifiers/dual_published.rb +55 -0
- data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +23 -0
- data/lib/pubid/ieee/identifiers/joint_development.rb +11 -7
- data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +57 -5
- data/lib/pubid/ieee/identifiers/nesc/base.rb +2 -2
- data/lib/pubid/ieee/identifiers/nesc/draft.rb +2 -2
- data/lib/pubid/ieee/identifiers/nesc/handbook.rb +2 -2
- data/lib/pubid/ieee/identifiers/nesc/redline.rb +2 -2
- data/lib/pubid/ieee/identifiers/nesc/standard.rb +2 -2
- data/lib/pubid/ieee/ire/identifier.rb +2 -2
- data/lib/pubid/ieee/ire/parser.rb +1 -1
- data/lib/pubid/ieee/nesc/parser.rb +1 -1
- data/lib/pubid/ieee/parser.rb +1 -1
- data/lib/pubid/ieee/renderer.rb +5 -1
- data/lib/pubid/ieee/urn_generator.rb +32 -3
- data/lib/pubid/ieee.rb +7 -1
- data/lib/pubid/ieee_debug.rb +1 -0
- data/lib/pubid/ietf/builder.rb +24 -8
- data/lib/pubid/ietf/identifiers/base.rb +25 -28
- data/lib/pubid/ietf/identifiers/bcp.rb +11 -0
- data/lib/pubid/ietf/identifiers/fyi.rb +11 -0
- data/lib/pubid/ietf/identifiers/internet_draft.rb +18 -2
- data/lib/pubid/ietf/identifiers/rfc.rb +2 -0
- data/lib/pubid/ietf/identifiers/serialization.rb +51 -0
- data/lib/pubid/ietf/identifiers/std.rb +11 -0
- data/lib/pubid/ietf/identifiers.rb +1 -0
- data/lib/pubid/ietf/parser.rb +27 -9
- data/lib/pubid/ietf/renderer.rb +44 -6
- data/lib/pubid/ietf/urn_generator.rb +20 -6
- data/lib/pubid/ietf/urn_parser.rb +10 -2
- data/lib/pubid/ietf.rb +12 -2
- data/lib/pubid/iho/identifiers/base.rb +10 -3
- data/lib/pubid/iho/parser.rb +1 -1
- data/lib/pubid/iho.rb +1 -0
- data/lib/pubid/isbn/identifier.rb +25 -7
- data/lib/pubid/isbn/parser.rb +1 -1
- data/lib/pubid/isbn.rb +1 -0
- data/lib/pubid/iso/bundled_identifier.rb +5 -3
- data/lib/pubid/iso/combined_identifier.rb +5 -3
- data/lib/pubid/iso/identifier.rb +12 -7
- data/lib/pubid/iso/identifiers/directives_supplement.rb +4 -4
- data/lib/pubid/iso/parser.rb +1 -1
- data/lib/pubid/iso.rb +7 -1
- data/lib/pubid/itu/identifiers/addendum.rb +2 -2
- data/lib/pubid/itu/identifiers/amendment.rb +2 -2
- data/lib/pubid/itu/identifiers/base.rb +19 -5
- data/lib/pubid/itu/identifiers/corrigendum.rb +2 -2
- data/lib/pubid/itu/identifiers/errata.rb +2 -2
- data/lib/pubid/itu/identifiers/supplement.rb +2 -2
- data/lib/pubid/itu/parser.rb +1 -1
- data/lib/pubid/itu.rb +1 -0
- data/lib/pubid/jcgm/builder.rb +1 -1
- data/lib/pubid/jcgm/identifier.rb +10 -0
- data/lib/pubid/jcgm/identifiers/meeting.rb +1 -1
- data/lib/pubid/jcgm/parser.rb +10 -3
- data/lib/pubid/jcgm/renderer.rb +10 -3
- data/lib/pubid/jcgm/single_identifier.rb +24 -15
- data/lib/pubid/jcgm/urn_generator.rb +1 -1
- data/lib/pubid/jcgm/urn_parser.rb +156 -14
- data/lib/pubid/jcgm.rb +10 -0
- data/lib/pubid/jis/identifier.rb +10 -3
- data/lib/pubid/jis/parser.rb +1 -1
- data/lib/pubid/jis.rb +1 -0
- data/lib/pubid/nist/components/stage.rb +2 -2
- data/lib/pubid/nist/configuration.rb +6 -8
- data/lib/pubid/nist/identifiers/base.rb +12 -2
- data/lib/pubid/nist/identifiers/circular.rb +9 -2
- data/lib/pubid/nist/identifiers/circular_supplement.rb +14 -5
- data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +7 -1
- data/lib/pubid/nist/identifiers/crpl_report.rb +7 -1
- data/lib/pubid/nist/identifiers/handbook.rb +9 -2
- data/lib/pubid/nist/identifiers/internal_report.rb +12 -5
- data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +14 -6
- data/lib/pubid/nist/identifiers/monograph.rb +14 -7
- data/lib/pubid/nist/identifiers/report.rb +14 -6
- data/lib/pubid/nist/parser.rb +1 -1
- data/lib/pubid/nist/supplement_identifier.rb +16 -1
- data/lib/pubid/nist.rb +7 -1
- data/lib/pubid/oasis/builder.rb +12 -10
- data/lib/pubid/oasis/identifier.rb +89 -11
- data/lib/pubid/oasis/parser.rb +1 -1
- data/lib/pubid/oasis.rb +7 -1
- data/lib/pubid/ogc/identifier.rb +9 -5
- data/lib/pubid/ogc/parser.rb +1 -1
- data/lib/pubid/ogc.rb +1 -0
- data/lib/pubid/oiml/builder.rb +5 -1
- data/lib/pubid/oiml/identifiers/basic_publication.rb +2 -0
- data/lib/pubid/oiml/identifiers/bulletin.rb +36 -0
- data/lib/pubid/oiml/identifiers/code_number.rb +90 -0
- data/lib/pubid/oiml/identifiers/document.rb +2 -0
- data/lib/pubid/oiml/identifiers/expert_report.rb +2 -0
- data/lib/pubid/oiml/identifiers/guide.rb +2 -0
- data/lib/pubid/oiml/identifiers/recommendation.rb +2 -0
- data/lib/pubid/oiml/identifiers/seminar_report.rb +2 -0
- data/lib/pubid/oiml/identifiers/vocabulary.rb +2 -0
- data/lib/pubid/oiml/identifiers.rb +1 -0
- data/lib/pubid/oiml/parser.rb +1 -1
- data/lib/pubid/oiml/single_identifier.rb +26 -42
- data/lib/pubid/oiml/supplement_identifier.rb +27 -0
- data/lib/pubid/oiml.rb +7 -1
- data/lib/pubid/omg/builder.rb +1 -0
- data/lib/pubid/omg/identifier.rb +20 -3
- data/lib/pubid/omg/parser.rb +64 -11
- data/lib/pubid/omg/renderer.rb +13 -1
- data/lib/pubid/omg.rb +2 -1
- data/lib/pubid/parser/grammar.rb +74 -0
- data/lib/pubid/parser.rb +2 -0
- data/lib/pubid/parsers/mr_string.rb +19 -0
- data/lib/pubid/plateau/parser.rb +1 -1
- data/lib/pubid/plateau.rb +10 -0
- data/lib/pubid/prefixes_support.rb +1 -0
- data/lib/pubid/renderers/annotator.rb +233 -0
- data/lib/pubid/renderers/base.rb +13 -0
- data/lib/pubid/renderers/directives_renderer.rb +3 -3
- data/lib/pubid/renderers/human_readable.rb +3 -3
- data/lib/pubid/renderers/mr_string.rb +15 -9
- data/lib/pubid/renderers.rb +1 -0
- data/lib/pubid/rendering/numbering.rb +25 -7
- data/lib/pubid/rendering.rb +1 -0
- data/lib/pubid/sae/identifiers/base.rb +9 -2
- data/lib/pubid/sae/parser.rb +1 -1
- data/lib/pubid/sae.rb +1 -0
- data/lib/pubid/schema/declaration.rb +33 -0
- data/lib/pubid/schema/error.rb +14 -0
- data/lib/pubid/schema/identifier_type.rb +23 -0
- data/lib/pubid/schema/loader.rb +117 -0
- data/lib/pubid/schema/typed_stage.rb +24 -0
- data/lib/pubid/schema.rb +25 -0
- data/lib/pubid/tgpp/builder.rb +1 -1
- data/lib/pubid/tgpp/identifier.rb +21 -5
- data/lib/pubid/tgpp/identifiers/technical_report.rb +2 -2
- data/lib/pubid/tgpp/identifiers/technical_specification.rb +2 -2
- data/lib/pubid/tgpp/parser.rb +22 -6
- data/lib/pubid/tgpp/renderer.rb +21 -5
- data/lib/pubid/tgpp/urn_generator.rb +27 -8
- data/lib/pubid/tgpp/urn_parser.rb +8 -6
- data/lib/pubid/tgpp.rb +7 -1
- data/lib/pubid/type_resolver.rb +16 -1
- data/lib/pubid/un/identifier.rb +6 -3
- data/lib/pubid/un/parser.rb +1 -1
- data/lib/pubid/un.rb +1 -0
- data/lib/pubid/urn_parser/errors.rb +8 -1
- data/lib/pubid/urn_parser.rb +1 -0
- data/lib/pubid/utils.rb +1 -0
- data/lib/pubid/version.rb +1 -1
- data/lib/pubid/w3c/builder.rb +5 -5
- data/lib/pubid/w3c/identifier.rb +38 -9
- data/lib/pubid/w3c/parser.rb +1 -1
- data/lib/pubid/w3c/renderer.rb +1 -1
- data/lib/pubid/w3c/urn_generator.rb +2 -2
- data/lib/pubid/w3c.rb +1 -0
- data/lib/pubid/xsf/identifier.rb +9 -5
- data/lib/pubid/xsf/parser.rb +17 -4
- data/lib/pubid/xsf.rb +7 -1
- data/lib/pubid.rb +399 -21
- data/lib/tasks/conformance.rake +34 -0
- data/lib/tasks/docs.rake +3 -3
- data/lib/tasks/schema.rake +88 -0
- data/schema/core/joint_prefixes.yaml +24 -0
- data/schema/iec.yaml +1017 -0
- data/schema/iso.yaml +1586 -0
- data/schema/schema.schema.yaml +96 -0
- metadata +38 -17
- data/archived-gems/pubid-ccsds/update_codes.yaml +0 -1
- data/archived-gems/pubid-iec/stages.yaml +0 -129
- data/archived-gems/pubid-iec/update_codes.yaml +0 -67
- data/archived-gems/pubid-ieee/update_codes.yaml +0 -104
- data/archived-gems/pubid-iso/stages.yaml +0 -106
- data/archived-gems/pubid-iso/update_codes.yaml +0 -4
- data/archived-gems/pubid-itu/i18n.yaml +0 -13
- data/archived-gems/pubid-itu/series.yaml +0 -42
- data/archived-gems/pubid-nist/publishers.yaml +0 -6
- data/archived-gems/pubid-nist/series.yaml +0 -121
- data/archived-gems/pubid-nist/update_codes.yaml +0 -93
- data/archived-gems/pubid-plateau/update_codes.yaml +0 -6
- data/lib/pubid/cen_cenelec/supplement_identifier.rb +0 -48
- data/lib/pubid/iec/components/code.rb +0 -36
- /data/{archived-gems/pubid-nist → data/nist}/stages.yaml +0 -0
data/lib/pubid/oasis/builder.rb
CHANGED
|
@@ -4,15 +4,17 @@ module Pubid
|
|
|
4
4
|
module Oasis
|
|
5
5
|
# Turns the parse tree into an `Identifiers::Standard`: stores the slug
|
|
6
6
|
# verbatim in `original`, then performs a best-effort, ORDER-INDEPENDENT
|
|
7
|
-
# decomposition into
|
|
7
|
+
# decomposition into number / version / stage / part / label.
|
|
8
8
|
#
|
|
9
9
|
# Decomposition splits `original` on "-" and classifies each *whole*
|
|
10
10
|
# fragment (so a stage-like substring inside a spec name — e.g. "CSDL" — is
|
|
11
|
-
# never mistaken for a stage). `
|
|
12
|
-
# before the first recognized fragment
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
11
|
+
# never mistaken for a stage). `number` is the specification name: the run
|
|
12
|
+
# of leading name fragments before the first recognized fragment, and the
|
|
13
|
+
# key relaton-index sorts and binary-searches on. `version`/`stage`/`part`
|
|
14
|
+
# are the first fragment of each recognized kind; `label` is any name
|
|
15
|
+
# fragment appearing after the first recognized one. Anything the
|
|
16
|
+
# classifier cannot place stays only in `original`, so the printed form
|
|
17
|
+
# always round-trips.
|
|
16
18
|
class Builder
|
|
17
19
|
# A fragment is a version when it is `v?N(.N)+` (e.g. "3.0", "v1.2.1",
|
|
18
20
|
# "V1.0"). Bare integers are deliberately NOT versions (too ambiguous
|
|
@@ -36,16 +38,16 @@ module Pubid
|
|
|
36
38
|
|
|
37
39
|
private
|
|
38
40
|
|
|
39
|
-
# @return [Hash] best-effort {
|
|
40
|
-
# Each fragment is classified once into a [fragment, kind] pair. `
|
|
41
|
-
# the leading run of name fragments; `label` is any name fragment after
|
|
41
|
+
# @return [Hash] best-effort { number:, version:, stage:, part:, label: }.
|
|
42
|
+
# Each fragment is classified once into a [fragment, kind] pair. `number`
|
|
43
|
+
# is the leading run of name fragments; `label` is any name fragment after
|
|
42
44
|
# the first recognized one; version/stage/part are the first of each kind.
|
|
43
45
|
def decompose(original)
|
|
44
46
|
pairs = original.split("-").map { |f| [f, classify(f)] }
|
|
45
47
|
lead = pairs.take_while { |_, kind| kind.nil? }
|
|
46
48
|
rest = pairs.drop(lead.length)
|
|
47
49
|
{
|
|
48
|
-
|
|
50
|
+
number: names(lead),
|
|
49
51
|
version: first_of(rest, :version),
|
|
50
52
|
stage: first_of(rest, :stage),
|
|
51
53
|
part: first_of(rest, :part),
|
|
@@ -16,15 +16,27 @@ module Pubid
|
|
|
16
16
|
# The exact slug printed after "OASIS " — always set. Drives `to_s`, so
|
|
17
17
|
# the printed form round-trips verbatim regardless of decomposition.
|
|
18
18
|
attribute :original, :string
|
|
19
|
-
# Best-effort decomposition (any may be nil). `
|
|
19
|
+
# Best-effort decomposition (any may be nil). `number`/`label` are plain
|
|
20
20
|
# slug fragments; `version`/`stage`/`part` carry the recognized fragment
|
|
21
21
|
# verbatim (e.g. "3.0", "v1.2.1", "PS01", "Errata01", "Pt8", "Part1").
|
|
22
|
-
|
|
22
|
+
#
|
|
23
|
+
# `number` holds the specification name ("OSLC-CM", "STIX", "amqp-core").
|
|
24
|
+
# It is the key relaton-index sorts and binary-searches on
|
|
25
|
+
# (`id.root.number.to_s`), and it deliberately CLUSTERS: every version,
|
|
26
|
+
# stage and part of one specification shares it, the same shape as an
|
|
27
|
+
# IETF draft slug or an IANA registry slug.
|
|
28
|
+
#
|
|
29
|
+
# `number`/`stage`/`part` intentionally override the inherited
|
|
30
|
+
# Components::Code / Components::Stage attributes with plain strings (the
|
|
31
|
+
# mechanism JIS uses for `number` and W3C for `date`): OASIS names,
|
|
32
|
+
# stages and parts are opaque tokens that must round-trip exactly and are
|
|
33
|
+
# never re-parsed as structured parts. Redefining an inherited attribute
|
|
34
|
+
# is only deterministic under multi-flavor load because this class body
|
|
35
|
+
# lives in ONE file and is never reopened, so lutaml has finished
|
|
36
|
+
# building the table before `Identifiers::Standard` snapshots it — DO NOT
|
|
37
|
+
# split this class across two files.
|
|
38
|
+
attribute :number, :string
|
|
23
39
|
attribute :version, :string
|
|
24
|
-
# `stage`/`part` intentionally override the inherited Components::Stage /
|
|
25
|
-
# Components::Code attributes with plain strings (same mechanism JIS uses
|
|
26
|
-
# for `number`, W3C for `date`): OASIS stages/parts are opaque tokens that
|
|
27
|
-
# must round-trip exactly and are never re-parsed as structured parts.
|
|
28
40
|
attribute :stage, :string
|
|
29
41
|
attribute :part, :string
|
|
30
42
|
attribute :label, :string
|
|
@@ -39,7 +51,7 @@ module Pubid
|
|
|
39
51
|
key_value do
|
|
40
52
|
map "_type", to: :_type, polymorphic_map: OASIS_TYPE_MAP
|
|
41
53
|
map "original", to: :original
|
|
42
|
-
map "
|
|
54
|
+
map "number", to: :number
|
|
43
55
|
map "version", to: :version
|
|
44
56
|
map "stage", to: :stage
|
|
45
57
|
map "part", to: :part
|
|
@@ -58,24 +70,90 @@ module Pubid
|
|
|
58
70
|
render(format: :human, **opts)
|
|
59
71
|
end
|
|
60
72
|
|
|
73
|
+
# The decomposition fields. Excluding any of them must also clear
|
|
74
|
+
# `original`, which still spells the excluded value out verbatim.
|
|
75
|
+
DECOMPOSITION_KEYS = %i[number version stage part label].freeze
|
|
76
|
+
|
|
77
|
+
# Widen a partial reference. `#matches?` is
|
|
78
|
+
# `exclude(*ignore) == other.exclude(*ignore)`, and `original` carries
|
|
79
|
+
# every component verbatim, so without this a bare "OASIS WSDM" could
|
|
80
|
+
# never match "OASIS WSDM-v1.1" however much the caller ignored.
|
|
81
|
+
#
|
|
82
|
+
# `original` is cleared ONLY when the exclusion touches the
|
|
83
|
+
# decomposition — the "reset the whole cluster" rule CSA applies to its
|
|
84
|
+
# year-format siblings. A plain `==` still compares `original`, so two
|
|
85
|
+
# slugs that decompose alike but print differently stay distinct: the
|
|
86
|
+
# decomposition loses fragment order and drops repeated fragments, so it
|
|
87
|
+
# is not by itself an identity.
|
|
88
|
+
def exclude(*args)
|
|
89
|
+
result = super
|
|
90
|
+
result.original = nil if args.intersect?(DECOMPOSITION_KEYS)
|
|
91
|
+
result
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# MR string hooks. `to_slug` delegates to `to_mr_string` and consumers
|
|
95
|
+
# use it as an output FILENAME, so the slug must be unique per document.
|
|
96
|
+
#
|
|
97
|
+
# The publisher lives in the PUBLISHER constant rather than the inherited
|
|
98
|
+
# lutaml attribute, so the base `mr_publisher` returns nil (the BIPM and
|
|
99
|
+
# IANA case) and is supplied here.
|
|
100
|
+
def mr_publisher
|
|
101
|
+
PUBLISHER.downcase
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# The whole verbatim slug, not the decomposed fields: decomposition loses
|
|
105
|
+
# fragment order and drops repeated fragments, so "x-1.0-os-Pt1" and
|
|
106
|
+
# "x-1.0-Pt1-os" would assemble to one slug. `original` cannot collide.
|
|
107
|
+
def mr_number_with_part
|
|
108
|
+
mr_sanitize(original)
|
|
109
|
+
end
|
|
110
|
+
|
|
61
111
|
# from_hash is the shared polymorphic dispatch on Pubid::Identifier;
|
|
62
112
|
# OASIS_TYPE_MAP remains as the key_value polymorphic_map.
|
|
63
113
|
|
|
64
114
|
# Parse an OASIS identifier string into an identifier object
|
|
65
115
|
# @param identifier [String] The OASIS identifier string to parse
|
|
66
116
|
# @return [Identifier] The Standard identifier object
|
|
67
|
-
# @raise [
|
|
117
|
+
# @raise [Pubid::Errors::ParseError] If parsing fails
|
|
68
118
|
def self.parse(identifier)
|
|
69
119
|
# Reject pathological inputs before they reach the parser
|
|
70
120
|
# (CodeQL rb/polynomial-redos barrier — inline .length by design).
|
|
121
|
+
unless identifier.is_a?(String)
|
|
122
|
+
raise Pubid::Errors::InvalidInputError,
|
|
123
|
+
Pubid::INPUT_NOT_A_STRING_MESSAGE
|
|
124
|
+
end
|
|
125
|
+
|
|
71
126
|
if identifier.length > Pubid::MAX_INPUT_LENGTH
|
|
72
|
-
raise
|
|
127
|
+
raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
|
|
73
128
|
end
|
|
74
129
|
|
|
75
130
|
parsed = Parser.parse(identifier)
|
|
76
131
|
Builder.build(parsed)
|
|
77
|
-
|
|
78
|
-
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
private
|
|
135
|
+
|
|
136
|
+
# Filter by CHARSET, not by an enumerated escape list, so a field added
|
|
137
|
+
# later cannot leak an unsafe character (the BIPM `mr_slug` precedent).
|
|
138
|
+
# Three characters need it today: the "." in every version —
|
|
139
|
+
# Renderers::MrString joins SEGMENTS with ".", so a dot inside one breaks
|
|
140
|
+
# the documented segment structure — plus the space and "]" of a few
|
|
141
|
+
# malformed records.
|
|
142
|
+
#
|
|
143
|
+
# A RUN of non-alphanumerics collapses to one "-", which is why "-" is
|
|
144
|
+
# outside the kept set (BIPM's form, not ETSI's): "v3.0]-PS01" would
|
|
145
|
+
# otherwise print a bare "--".
|
|
146
|
+
#
|
|
147
|
+
# Caveat, the same one BIPM records: "-" is both the intra-slug join and
|
|
148
|
+
# the substitute, so two slugs differing ONLY in which non-slug character
|
|
149
|
+
# they use collapse onto one MR string. The corpus has exactly one such
|
|
150
|
+
# pair, the malformed "OpenC2-MQTT-v1.0] -CS01" spelled once with a
|
|
151
|
+
# normal space and once with a non-breaking one — two spellings of one
|
|
152
|
+
# document. Every genuinely distinct identifier keeps its own slug.
|
|
153
|
+
def mr_sanitize(value)
|
|
154
|
+
slug = value.to_s.downcase.gsub(/[^a-z0-9]+/, "-")
|
|
155
|
+
.gsub(/\A-+|-+\z/, "")
|
|
156
|
+
slug.empty? ? nil : slug
|
|
79
157
|
end
|
|
80
158
|
end
|
|
81
159
|
end
|
data/lib/pubid/oasis/parser.rb
CHANGED
|
@@ -16,7 +16,7 @@ module Pubid
|
|
|
16
16
|
# Builder with order-independent fragment classification. Keeping
|
|
17
17
|
# decomposition out of the PEG avoids brittle backtracking and guarantees a
|
|
18
18
|
# lossless round-trip.
|
|
19
|
-
class Parser <
|
|
19
|
+
class Parser < ::Pubid::Parser::Grammar
|
|
20
20
|
rule(:prefix) { str("OASIS") >> str(" ") }
|
|
21
21
|
|
|
22
22
|
# The whole slug, captured verbatim (any character, incl. spaces / "]").
|
data/lib/pubid/oasis.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "pubid"
|
|
3
4
|
module Pubid
|
|
4
5
|
module Oasis
|
|
5
6
|
extend Pubid::PrefixesSupport
|
|
@@ -21,8 +22,13 @@ module Pubid
|
|
|
21
22
|
def self.parse(identifier)
|
|
22
23
|
# Reject pathological inputs before they reach the parser
|
|
23
24
|
# (CodeQL rb/polynomial-redos barrier — inline .length by design).
|
|
25
|
+
unless identifier.is_a?(String)
|
|
26
|
+
raise Pubid::Errors::InvalidInputError,
|
|
27
|
+
Pubid::INPUT_NOT_A_STRING_MESSAGE
|
|
28
|
+
end
|
|
29
|
+
|
|
24
30
|
if identifier.length > Pubid::MAX_INPUT_LENGTH
|
|
25
|
-
raise
|
|
31
|
+
raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
|
|
26
32
|
end
|
|
27
33
|
|
|
28
34
|
Identifier.parse(identifier)
|
data/lib/pubid/ogc/identifier.rb
CHANGED
|
@@ -61,16 +61,20 @@ module Pubid
|
|
|
61
61
|
# Parse an OGC identifier string into an identifier object.
|
|
62
62
|
# @param identifier [String] The OGC identifier string to parse
|
|
63
63
|
# @return [Identifier] The document identifier object
|
|
64
|
-
# @raise [
|
|
65
|
-
#
|
|
64
|
+
# @raise [Pubid::Errors::InvalidInputError]
|
|
65
|
+
# If the input exceeds the maximum length
|
|
66
|
+
# @raise [Pubid::Errors::ParseError] If parsing fails
|
|
66
67
|
def self.parse(identifier)
|
|
68
|
+
unless identifier.is_a?(String)
|
|
69
|
+
raise Pubid::Errors::InvalidInputError,
|
|
70
|
+
Pubid::INPUT_NOT_A_STRING_MESSAGE
|
|
71
|
+
end
|
|
72
|
+
|
|
67
73
|
if identifier.length > Pubid::MAX_INPUT_LENGTH
|
|
68
|
-
raise
|
|
74
|
+
raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
|
|
69
75
|
end
|
|
70
76
|
|
|
71
77
|
Builder.build(Parser.parse(identifier))
|
|
72
|
-
rescue Parslet::ParseFailed => e
|
|
73
|
-
raise "Failed to parse OGC identifier '#{identifier}': #{e.message}"
|
|
74
78
|
end
|
|
75
79
|
end
|
|
76
80
|
end
|
data/lib/pubid/ogc/parser.rb
CHANGED
|
@@ -12,7 +12,7 @@ module Pubid
|
|
|
12
12
|
# leniency, though the canonical printed form omits it.
|
|
13
13
|
#
|
|
14
14
|
# Examples: "25-023", "24-032r1", "01-009a", "04-095c1", "OGC 24-032r1".
|
|
15
|
-
class Parser <
|
|
15
|
+
class Parser < ::Pubid::Parser::Grammar
|
|
16
16
|
rule(:space) { match["\\s"].repeat(1) }
|
|
17
17
|
rule(:digits) { match["0-9"].repeat(1) }
|
|
18
18
|
|
data/lib/pubid/ogc.rb
CHANGED
data/lib/pubid/oiml/builder.rb
CHANGED
|
@@ -152,7 +152,11 @@ module Pubid
|
|
|
152
152
|
code_attrs[:suffix] = parsed_hash[:code_suffix].to_s
|
|
153
153
|
code_attrs[:space_suffix] = true if parsed_hash.key?(:space_suffix)
|
|
154
154
|
end
|
|
155
|
-
|
|
155
|
+
# The code fields are flat index columns on the leaf (see
|
|
156
|
+
# Identifiers::CodeNumber) — `number` is what relaton-index keys on —
|
|
157
|
+
# so they are assigned individually rather than as a Code object.
|
|
158
|
+
# Bulletin has no code columns and never reaches this branch.
|
|
159
|
+
code_attrs.each { |name, value| identifier.public_send(:"#{name}=", value) }
|
|
156
160
|
end
|
|
157
161
|
|
|
158
162
|
# Handle other attributes
|
|
@@ -45,6 +45,42 @@ module Pubid
|
|
|
45
45
|
map "sequence", to: :sequence
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
# relaton-index keys on `id.root.number.to_s`. Bulletin is the one OIML
|
|
49
|
+
# leaf with no code (it does not include Identifiers::CodeNumber), so
|
|
50
|
+
# it derives the key from the year it already stores: every issue and
|
|
51
|
+
# article of a volume clusters into one bucket, with per-article
|
|
52
|
+
# distinctness coming from the MR slug instead. That is the BIPM
|
|
53
|
+
# Metrologia-volume precedent recorded in CLAUDE.md.
|
|
54
|
+
#
|
|
55
|
+
# A DERIVED READER, deliberately not an attribute: storing it would
|
|
56
|
+
# duplicate `year` in every row, and the key_value block above maps no
|
|
57
|
+
# "number", so nothing is added to the wire format. Safe as a plain
|
|
58
|
+
# method because Bulletin declares no `number` attribute of its own
|
|
59
|
+
# (the ITU itu/identifiers/base.rb precedent).
|
|
60
|
+
#
|
|
61
|
+
# nil for the bare periodical reference "OIML Bulletin", which names no
|
|
62
|
+
# year — a deliberate gap, pinned in spec/pubid/oiml/root_number_spec.rb.
|
|
63
|
+
def number
|
|
64
|
+
date&.year&.to_s
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# The index key above is deliberately coarse — a whole volume in one
|
|
68
|
+
# bucket — which is only defensible because the MR slug stays
|
|
69
|
+
# per-article. The inherited hook reads through `code`, which Bulletin
|
|
70
|
+
# does not have, so it would return nil and collapse every article of a
|
|
71
|
+
# year onto `oiml.bulletin.<year>`; `to_slug` is an output FILENAME, so
|
|
72
|
+
# that is an overwrite. Emit the rest of the locator instead.
|
|
73
|
+
#
|
|
74
|
+
# The year is deliberately NOT included: Renderers::MrString already
|
|
75
|
+
# gives it its own segment (`mr_year`), so repeating it here would
|
|
76
|
+
# render `oiml.bulletin.1960-03-01.1960`.
|
|
77
|
+
def mr_number_with_part
|
|
78
|
+
segments = [issue, sequence].compact
|
|
79
|
+
return nil if segments.empty?
|
|
80
|
+
|
|
81
|
+
segments.join("-")
|
|
82
|
+
end
|
|
83
|
+
|
|
48
84
|
def type_string
|
|
49
85
|
"Bulletin"
|
|
50
86
|
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Oiml
|
|
5
|
+
module Identifiers
|
|
6
|
+
# Installs the flat, index-friendly code columns and their serialization
|
|
7
|
+
# on the seven concrete OIML document leaves (Recommendation, Document,
|
|
8
|
+
# Vocabulary, Guide, BasicPublication, ExpertReport, SeminarReport).
|
|
9
|
+
#
|
|
10
|
+
# Why the leaves and not Pubid::Oiml::SingleIdentifier, which they all
|
|
11
|
+
# inherit from: `number` redefines the parent ::Pubid::Identifier's
|
|
12
|
+
# `attribute :number, Components::Code` as a plain :string (and `part` /
|
|
13
|
+
# `subpart` likewise). Declaring that on a class the concrete types
|
|
14
|
+
# INHERIT from resolves against the parent definition nondeterministically
|
|
15
|
+
# under multi-flavor load — it passes an OIML-only run and can flip
|
|
16
|
+
# `root.number` to "" under the full suite (the IEEE lesson; see
|
|
17
|
+
# lib/pubid/ieee/identifiers/code_number.rb and CLAUDE.md). Declaring on
|
|
18
|
+
# each leaf removes the ambiguity at the point of use.
|
|
19
|
+
#
|
|
20
|
+
# This matters because relaton-index sorts and bsearches every row on
|
|
21
|
+
# `id.root.number.to_s`. OIML kept the code in an Oiml::Components::Code
|
|
22
|
+
# under a `code` attribute and never set `number`, so all 12,226 lines of
|
|
23
|
+
# the published relaton-data-oiml index-v2 keyed "".
|
|
24
|
+
#
|
|
25
|
+
# The serialized hash ALREADY had these as bare top-level scalars — the
|
|
26
|
+
# old converters merely read them through `code` — so the wire format is
|
|
27
|
+
# byte-identical and that index needs no regeneration.
|
|
28
|
+
#
|
|
29
|
+
# Bulletin deliberately does NOT include this module. It carries no code
|
|
30
|
+
# at all (its locator is the year/issue/sequence tuple), so it would only
|
|
31
|
+
# gain a permanently-nil `number` and a `number` key that never appears.
|
|
32
|
+
# It derives its index key from the year instead; see bulletin.rb.
|
|
33
|
+
module CodeNumber
|
|
34
|
+
def self.included(base)
|
|
35
|
+
install_attributes(base)
|
|
36
|
+
install_mappings(base)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.install_attributes(base)
|
|
40
|
+
# Bare document number ("144"), the relaton index key. The part is a
|
|
41
|
+
# sibling column, never folded in, so every part of a document shares
|
|
42
|
+
# one bucket and a part-less reference finds them all.
|
|
43
|
+
base.attribute :number, :string
|
|
44
|
+
base.attribute :part, :string
|
|
45
|
+
base.attribute :subpart, :string
|
|
46
|
+
# Free-form trailing suffix glued to the code, e.g. "sup", "A",
|
|
47
|
+
# "erratum", "GUM 1", "ISO3930". Preserved verbatim for round-trip.
|
|
48
|
+
base.attribute :suffix, :string
|
|
49
|
+
# When true the suffix is space-separated ("D 1 Brochure") rather
|
|
50
|
+
# than the default dash ("R 60-sup"). Named for the RARE case with a
|
|
51
|
+
# false default, so the canonical to_hash drops it from every
|
|
52
|
+
# ordinary row.
|
|
53
|
+
base.attribute :space_suffix, :boolean, default: -> { false }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Merged by lutaml with the block SingleIdentifier declares, which
|
|
57
|
+
# carries publisher/year/edition/stage/iteration.
|
|
58
|
+
def self.install_mappings(base)
|
|
59
|
+
base.key_value do
|
|
60
|
+
map "number", to: :number
|
|
61
|
+
map "part", to: :part
|
|
62
|
+
map "subpart", to: :subpart
|
|
63
|
+
map "suffix", to: :suffix
|
|
64
|
+
map "space_suffix", to: :space_suffix
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# The composed document code, rebuilt on demand from the split columns
|
|
69
|
+
# so the renderer and the URN generator keep one place to ask for the
|
|
70
|
+
# printed form ("144-1", "60-sup"). Deliberately NOT an attribute and
|
|
71
|
+
# NOT memoised: the columns are writable (the base #exclude rebuilds
|
|
72
|
+
# through them), so a cached Code would go stale.
|
|
73
|
+
#
|
|
74
|
+
# nil when there is no number, preserving the old nil-`code` semantics
|
|
75
|
+
# the URN generator branches on.
|
|
76
|
+
def code
|
|
77
|
+
return nil if number.nil?
|
|
78
|
+
|
|
79
|
+
Components::Code.new(
|
|
80
|
+
number: number,
|
|
81
|
+
part: part,
|
|
82
|
+
subpart: subpart,
|
|
83
|
+
suffix: suffix,
|
|
84
|
+
space_suffix: space_suffix,
|
|
85
|
+
)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -7,6 +7,7 @@ module Pubid
|
|
|
7
7
|
autoload :Annex, "#{__dir__}/identifiers/annex"
|
|
8
8
|
autoload :BasicPublication, "#{__dir__}/identifiers/basic_publication"
|
|
9
9
|
autoload :Bulletin, "#{__dir__}/identifiers/bulletin"
|
|
10
|
+
autoload :CodeNumber, "#{__dir__}/identifiers/code_number"
|
|
10
11
|
autoload :Document, "#{__dir__}/identifiers/document"
|
|
11
12
|
autoload :Errata, "#{__dir__}/identifiers/errata"
|
|
12
13
|
autoload :ExpertReport, "#{__dir__}/identifiers/expert_report"
|
data/lib/pubid/oiml/parser.rb
CHANGED
|
@@ -5,7 +5,6 @@ module Pubid
|
|
|
5
5
|
class SingleIdentifier < Identifier
|
|
6
6
|
# Base class for OIML single identifiers (non-supplements)
|
|
7
7
|
attribute :publisher, :string
|
|
8
|
-
attribute :code, Oiml::Components::Code
|
|
9
8
|
attribute :date, Pubid::Components::Date
|
|
10
9
|
attribute :edition, :string
|
|
11
10
|
attribute :stage, :string
|
|
@@ -16,46 +15,24 @@ module Pubid
|
|
|
16
15
|
} # Track parsed format
|
|
17
16
|
|
|
18
17
|
# Serialization delta on top of Oiml::Identifier's shared block. The
|
|
19
|
-
# `
|
|
20
|
-
#
|
|
21
|
-
# (
|
|
22
|
-
#
|
|
18
|
+
# `date` (year) component is flattened to a top-level key rather than a
|
|
19
|
+
# nested hash, mirroring ISO (lib/pubid/iso/identifier.rb). `type` is
|
|
20
|
+
# intentionally omitted (recomputed from the class on load).
|
|
21
|
+
#
|
|
22
|
+
# The code columns (number/part/subpart/suffix/space_suffix) are NOT
|
|
23
|
+
# here: they are declared, and mapped, by Identifiers::CodeNumber on each
|
|
24
|
+
# concrete leaf, because redefining the inherited `number` on this class
|
|
25
|
+
# — which every leaf inherits — is the multi-flavor determinism landmine.
|
|
26
|
+
# Keeping the mapping with the attribute is also what lets Bulletin, the
|
|
27
|
+
# one leaf with no code, omit both.
|
|
23
28
|
key_value do
|
|
24
29
|
map "publisher", to: :publisher
|
|
25
|
-
map "number", with: { to: :number_to_kv, from: :number_from_kv }
|
|
26
|
-
map "part", with: { to: :part_to_kv, from: :part_from_kv }
|
|
27
|
-
map "subpart", with: { to: :subpart_to_kv, from: :subpart_from_kv }
|
|
28
|
-
map "suffix", with: { to: :suffix_to_kv, from: :suffix_from_kv }
|
|
29
|
-
map "space_suffix",
|
|
30
|
-
with: { to: :space_suffix_to_kv, from: :space_suffix_from_kv }
|
|
31
30
|
map "year", with: { to: :year_to_kv, from: :year_from_kv }
|
|
32
31
|
map "edition", to: :edition
|
|
33
32
|
map "stage", to: :stage
|
|
34
33
|
map "iteration", to: :iteration
|
|
35
34
|
end
|
|
36
35
|
|
|
37
|
-
# --- code components flattened to top-level keys ---
|
|
38
|
-
def number_to_kv(model, doc) = emit_kv(doc, "number", model.code&.number)
|
|
39
|
-
def number_from_kv(model, value) = code_for(model).number = value.to_s
|
|
40
|
-
def part_to_kv(model, doc) = emit_kv(doc, "part", model.code&.part)
|
|
41
|
-
def part_from_kv(model, value) = code_for(model).part = value.to_s
|
|
42
|
-
def subpart_to_kv(model, doc) = emit_kv(doc, "subpart", model.code&.subpart)
|
|
43
|
-
def subpart_from_kv(model, value) = code_for(model).subpart = value.to_s
|
|
44
|
-
def suffix_to_kv(model, doc) = emit_kv(doc, "suffix", model.code&.suffix)
|
|
45
|
-
def suffix_from_kv(model, value) = code_for(model).suffix = value.to_s
|
|
46
|
-
|
|
47
|
-
def space_suffix_to_kv(model, doc)
|
|
48
|
-
return unless model.code&.space_suffix
|
|
49
|
-
|
|
50
|
-
doc.add_child(
|
|
51
|
-
Lutaml::KeyValue::DataModel::Element.new("space_suffix", true),
|
|
52
|
-
)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def space_suffix_from_kv(model, value)
|
|
56
|
-
code_for(model).space_suffix = value
|
|
57
|
-
end
|
|
58
|
-
|
|
59
36
|
# --- date flattened to a top-level year ---
|
|
60
37
|
def year_to_kv(model, doc) = emit_kv(doc, "year", model.date&.year)
|
|
61
38
|
|
|
@@ -69,10 +46,6 @@ module Pubid
|
|
|
69
46
|
doc.add_child(Lutaml::KeyValue::DataModel::Element.new(key, value.to_s))
|
|
70
47
|
end
|
|
71
48
|
|
|
72
|
-
def code_for(model)
|
|
73
|
-
model.code ||= Components::Code.new
|
|
74
|
-
end
|
|
75
|
-
|
|
76
49
|
attr_reader :requested_format
|
|
77
50
|
|
|
78
51
|
# Type is determined by the subclass
|
|
@@ -103,11 +76,15 @@ module Pubid
|
|
|
103
76
|
raise NotImplementedError, "Subclasses must implement type_string"
|
|
104
77
|
end
|
|
105
78
|
|
|
106
|
-
# OIML keeps identity in
|
|
107
|
-
#
|
|
108
|
-
#
|
|
109
|
-
#
|
|
110
|
-
#
|
|
79
|
+
# OIML keeps identity in the code columns and `type_string` (e.g. "R",
|
|
80
|
+
# "V", "D"), not in the inherited `typed_stage` — the generic MrString
|
|
81
|
+
# renderer would otherwise drop both and produce `OIML.<year>`.
|
|
82
|
+
# Losslessness for issue #142 requires the type letter and document
|
|
83
|
+
# number to appear in MR.
|
|
84
|
+
#
|
|
85
|
+
# Reads through `code`, which every code-bearing leaf composes from its
|
|
86
|
+
# split columns (Identifiers::CodeNumber); Bulletin has no code and
|
|
87
|
+
# returns nil here, keeping its (year, issue, sequence) slug.
|
|
111
88
|
def mr_number_with_part
|
|
112
89
|
segments = []
|
|
113
90
|
segments << code&.number&.to_s if code&.number
|
|
@@ -119,6 +96,13 @@ module Pubid
|
|
|
119
96
|
segments.join("-")
|
|
120
97
|
end
|
|
121
98
|
|
|
99
|
+
# Bulletin overrides `code`; every other leaf gets it from
|
|
100
|
+
# Identifiers::CodeNumber. Returning nil here keeps #== , the renderer
|
|
101
|
+
# and the URN generator total for the abstract class itself.
|
|
102
|
+
def code
|
|
103
|
+
nil
|
|
104
|
+
end
|
|
105
|
+
|
|
122
106
|
def mr_type
|
|
123
107
|
type_string&.downcase
|
|
124
108
|
end
|
|
@@ -8,6 +8,33 @@ module Pubid
|
|
|
8
8
|
attribute :base, Oiml::Identifier, polymorphic: true
|
|
9
9
|
attribute :year, :string
|
|
10
10
|
attribute :language, :string
|
|
11
|
+
|
|
12
|
+
# Delegate the document code to the wrapped standard, mirroring
|
|
13
|
+
# Pubid::Etsi::Identifiers::SupplementIdentifier#code.
|
|
14
|
+
#
|
|
15
|
+
# PRE-EXISTING BUG this closes: `UrnGenerator#urn_number` calls
|
|
16
|
+
# `identifier.code` for every non-Bulletin type, but a supplement
|
|
17
|
+
# descends from Oiml::Identifier directly — it is a SIBLING of
|
|
18
|
+
# SingleIdentifier, which is where `code` used to live — so it inherited
|
|
19
|
+
# no `code` at all and `to_urn` raised NoMethodError for every Amendment,
|
|
20
|
+
# Errata and Annex. Verified against a baseline captured on main: all
|
|
21
|
+
# five supplement fixtures already raised there, so this is a fix, not a
|
|
22
|
+
# regression introduced by the move to split index columns.
|
|
23
|
+
#
|
|
24
|
+
# It stayed hidden because spec/pubid/oiml/urn_spec.rb only exercises a
|
|
25
|
+
# bare Recommendation and spec/pubid/oiml/fixtures_spec.rb globs a bad
|
|
26
|
+
# path and runs 0 examples (hand-off: ten-dead-fixture-specs).
|
|
27
|
+
# `iteration` is the same story: declared on SingleIdentifier, read
|
|
28
|
+
# unconditionally by UrnGenerator#urn_iteration, absent from the
|
|
29
|
+
# supplement branch of the hierarchy. (`stage` escapes because
|
|
30
|
+
# ::Pubid::Identifier declares one, so it merely returns nil.)
|
|
31
|
+
def code
|
|
32
|
+
base&.code
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def iteration
|
|
36
|
+
base&.iteration
|
|
37
|
+
end
|
|
11
38
|
# True for the trailing-word shorthand ("OIML R 138:2009 Amendment"),
|
|
12
39
|
# where the supplement word is appended after a dated base instead of the
|
|
13
40
|
# "Amendment (YYYY) to BASE" prose form. The word itself comes from the
|