pubid 2.0.0.pre.alpha.7 → 2.0.0.pre.alpha.9
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 +9 -50
- data/data/bipm/update_codes.yaml +9 -0
- data/data/iec/update_codes.yaml +3 -0
- data/data/ieee/update_codes.yaml +107 -1
- data/data/nist/series.yaml +155 -0
- data/data/nist/update_codes.yaml +8 -0
- data/lib/pubid/adobe/builder.rb +52 -0
- data/lib/pubid/adobe/identifier.rb +49 -0
- data/lib/pubid/adobe/identifiers/publication.rb +31 -0
- data/lib/pubid/adobe/identifiers/tech_note.rb +32 -0
- data/lib/pubid/adobe/identifiers.rb +10 -0
- data/lib/pubid/adobe/parser.rb +128 -0
- data/lib/pubid/adobe/renderer.rb +39 -0
- data/lib/pubid/adobe/urn_generator.rb +42 -0
- data/lib/pubid/adobe/urn_parser.rb +69 -0
- data/lib/pubid/adobe.rb +60 -0
- data/lib/pubid/amca/builder.rb +2 -2
- data/lib/pubid/amca/identifier.rb +1 -3
- data/lib/pubid/amca/identifiers/base.rb +1 -6
- data/lib/pubid/amca/identifiers/interpretation.rb +1 -1
- data/lib/pubid/amca/identifiers/publication.rb +1 -1
- data/lib/pubid/amca/identifiers/standard.rb +1 -1
- data/lib/pubid/amca/identifiers.rb +0 -1
- data/lib/pubid/amca/single_identifier.rb +1 -1
- data/lib/pubid/amca.rb +3 -3
- data/lib/pubid/ashrae/builder.rb +22 -22
- data/lib/pubid/ashrae/identifier.rb +3 -4
- data/lib/pubid/ashrae/identifiers/addenda_package.rb +1 -1
- data/lib/pubid/ashrae/identifiers/addendum.rb +1 -1
- data/lib/pubid/ashrae/identifiers/base.rb +14 -8
- data/lib/pubid/ashrae/identifiers/combined_addenda.rb +1 -1
- data/lib/pubid/ashrae/identifiers.rb +0 -1
- data/lib/pubid/ashrae/parser.rb +14 -9
- data/lib/pubid/ashrae/renderer.rb +19 -19
- data/lib/pubid/ashrae/single_identifier.rb +1 -1
- data/lib/pubid/ashrae/supplement_identifier.rb +6 -6
- data/lib/pubid/ashrae.rb +3 -3
- data/lib/pubid/bipm/builder.rb +107 -0
- data/lib/pubid/bipm/identifier.rb +160 -0
- data/lib/pubid/bipm/identifiers/committee_document.rb +24 -0
- data/lib/pubid/bipm/identifiers/guide.rb +24 -0
- data/lib/pubid/bipm/identifiers/meeting.rb +41 -0
- data/lib/pubid/bipm/identifiers/mep.rb +21 -0
- data/lib/pubid/bipm/identifiers/metrologia_article.rb +24 -0
- data/lib/pubid/bipm/identifiers/si_brochure.rb +20 -0
- data/lib/pubid/bipm/identifiers.rb +15 -0
- data/lib/pubid/bipm/parser.rb +184 -0
- data/lib/pubid/bipm/renderer.rb +110 -0
- data/lib/pubid/bipm/urn_generator.rb +58 -0
- data/lib/pubid/bipm/urn_parser.rb +52 -0
- data/lib/pubid/bipm.rb +86 -0
- data/lib/pubid/bsi/builder.rb +14 -14
- data/lib/pubid/bsi/identifier.rb +0 -1
- data/lib/pubid/bsi/identifiers/addendum_document.rb +2 -2
- data/lib/pubid/bsi/identifiers/amendment.rb +4 -4
- data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +6 -0
- data/lib/pubid/bsi/identifiers/corrigendum.rb +4 -4
- data/lib/pubid/bsi/identifiers/expert_commentary.rb +5 -5
- data/lib/pubid/bsi/identifiers/supplement_document.rb +2 -2
- data/lib/pubid/bsi/identifiers/value_added_publication.rb +6 -6
- data/lib/pubid/bsi/renderer.rb +8 -8
- data/lib/pubid/bsi/single_identifier.rb +48 -0
- data/lib/pubid/builder/base.rb +5 -3
- data/lib/pubid/bundled_identifier.rb +3 -3
- data/lib/pubid/calconnect/builder.rb +38 -0
- data/lib/pubid/calconnect/identifier.rb +117 -0
- data/lib/pubid/calconnect/identifiers/standard.rb +29 -0
- data/lib/pubid/calconnect/identifiers.rb +9 -0
- data/lib/pubid/calconnect/parser.rb +54 -0
- data/lib/pubid/calconnect/renderer.rb +36 -0
- data/lib/pubid/calconnect/urn_generator.rb +33 -0
- data/lib/pubid/calconnect/urn_parser.rb +34 -0
- data/lib/pubid/calconnect.rb +77 -0
- data/lib/pubid/ccsds/builder.rb +1 -1
- data/lib/pubid/ccsds/identifier.rb +1 -1
- data/lib/pubid/ccsds/identifiers/corrigendum.rb +2 -2
- data/lib/pubid/ccsds/supplement_identifier.rb +6 -6
- data/lib/pubid/ccsds/urn_generator.rb +3 -3
- data/lib/pubid/cen_cenelec/builder.rb +46 -12
- data/lib/pubid/cen_cenelec/identifiers/amendment.rb +2 -2
- data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +6 -0
- data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +2 -2
- data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +60 -3
- data/lib/pubid/cen_cenelec/identifiers/fragment.rb +2 -2
- data/lib/pubid/cen_cenelec/renderer.rb +5 -5
- data/lib/pubid/cen_cenelec/supplement_identifier.rb +5 -5
- data/lib/pubid/cen_cenelec/urn_generator.rb +1 -1
- data/lib/pubid/cen_cenelec.rb +76 -72
- data/lib/pubid/cie/builder.rb +139 -24
- data/lib/pubid/cie/identifier.rb +7 -3
- data/lib/pubid/cie/identifiers/bundle.rb +32 -4
- data/lib/pubid/cie/identifiers/code_attributes.rb +52 -0
- data/lib/pubid/cie/identifiers/conference.rb +9 -4
- data/lib/pubid/cie/identifiers/corrigendum.rb +17 -23
- data/lib/pubid/cie/identifiers/dual_published.rb +4 -4
- data/lib/pubid/cie/identifiers/identical.rb +7 -7
- data/lib/pubid/cie/identifiers/joint_published.rb +8 -8
- data/lib/pubid/cie/identifiers/proceedings.rb +39 -0
- data/lib/pubid/cie/identifiers/standard.rb +33 -7
- data/lib/pubid/cie/identifiers/supplement.rb +24 -22
- data/lib/pubid/cie/identifiers/tutorial_bundle.rb +6 -2
- data/lib/pubid/cie/identifiers.rb +2 -0
- data/lib/pubid/cie/parser.rb +54 -5
- data/lib/pubid/cie/single_identifier.rb +40 -1
- data/lib/pubid/cie/supplement_identifier.rb +29 -16
- data/lib/pubid/cie/urn_generator.rb +11 -8
- data/lib/pubid/cie.rb +0 -1
- data/lib/pubid/components/date.rb +21 -5
- data/lib/pubid/csa/builder.rb +1 -1
- data/lib/pubid/csa/composite_identifier.rb +17 -1
- data/lib/pubid/csa/identifier.rb +48 -3
- data/lib/pubid/csa/identifiers/bundled.rb +6 -0
- data/lib/pubid/csa/identifiers/combined.rb +6 -0
- data/lib/pubid/csa/identifiers/package.rb +2 -2
- data/lib/pubid/csa/parser.rb +6 -6
- data/lib/pubid/csa/wrapper_identifier.rb +17 -0
- data/lib/pubid/doi/builder.rb +18 -0
- data/lib/pubid/doi/identifier.rb +46 -0
- data/lib/pubid/doi/identifiers/resource.rb +30 -0
- data/lib/pubid/doi/identifiers.rb +9 -0
- data/lib/pubid/doi/parser.rb +52 -0
- data/lib/pubid/doi/renderer.rb +13 -0
- data/lib/pubid/doi.rb +55 -0
- data/lib/pubid/easc/builder.rb +55 -0
- data/lib/pubid/easc/identifier.rb +61 -0
- data/lib/pubid/easc/identifiers/pmg.rb +20 -0
- data/lib/pubid/easc/identifiers/rmg.rb +19 -0
- data/lib/pubid/easc/identifiers.rb +10 -0
- data/lib/pubid/easc/parser.rb +80 -0
- data/lib/pubid/easc/renderer.rb +48 -0
- data/lib/pubid/easc/urn_generator.rb +46 -0
- data/lib/pubid/easc/urn_parser.rb +57 -0
- data/lib/pubid/easc.rb +52 -0
- data/lib/pubid/ecma/builder.rb +31 -0
- data/lib/pubid/ecma/identifier.rb +76 -0
- data/lib/pubid/ecma/identifiers/memento.rb +30 -0
- data/lib/pubid/ecma/identifiers/standard.rb +31 -0
- data/lib/pubid/ecma/identifiers/technical_report.rb +31 -0
- data/lib/pubid/ecma/identifiers.rb +11 -0
- data/lib/pubid/ecma/parser.rb +41 -0
- data/lib/pubid/ecma/renderer.rb +46 -0
- data/lib/pubid/ecma/urn_generator.rb +25 -0
- data/lib/pubid/ecma/urn_parser.rb +35 -0
- data/lib/pubid/ecma.rb +67 -0
- data/lib/pubid/etsi/builder.rb +7 -3
- data/lib/pubid/etsi/identifier.rb +1 -3
- data/lib/pubid/etsi/identifiers/base.rb +28 -10
- data/lib/pubid/etsi/identifiers/etsi_standard.rb +128 -4
- data/lib/pubid/etsi/identifiers/supplement_identifier.rb +35 -3
- data/lib/pubid/etsi/identifiers.rb +0 -1
- data/lib/pubid/etsi/parser.rb +8 -2
- data/lib/pubid/etsi/renderer.rb +8 -2
- data/lib/pubid/etsi.rb +5 -5
- data/lib/pubid/export/exporter.rb +2 -1
- data/lib/pubid/export/flavor_exporter.rb +18 -3
- data/lib/pubid/gb/builder.rb +45 -0
- data/lib/pubid/gb/identifier.rb +64 -0
- data/lib/pubid/gb/identifiers/standard.rb +34 -0
- data/lib/pubid/gb/identifiers.rb +9 -0
- data/lib/pubid/gb/parser.rb +63 -0
- data/lib/pubid/gb/renderer.rb +35 -0
- data/lib/pubid/gb.rb +87 -0
- data/lib/pubid/gost/builder.rb +148 -0
- data/lib/pubid/gost/identifier.rb +49 -0
- data/lib/pubid/gost/identifiers/foreign_reference.rb +25 -0
- data/lib/pubid/gost/identifiers/harmonized.rb +39 -0
- data/lib/pubid/gost/identifiers/identical_adoption.rb +39 -0
- data/lib/pubid/gost/identifiers/interstate_standard.rb +20 -0
- data/lib/pubid/gost/identifiers/national_standard.rb +19 -0
- data/lib/pubid/gost/identifiers.rb +13 -0
- data/lib/pubid/gost/parser.rb +97 -0
- data/lib/pubid/gost/renderer.rb +48 -0
- data/lib/pubid/gost/urn_generator.rb +46 -0
- data/lib/pubid/gost/urn_parser.rb +52 -0
- data/lib/pubid/gost.rb +49 -0
- data/lib/pubid/iala/builder.rb +22 -27
- data/lib/pubid/iala/identifier.rb +27 -2
- data/lib/pubid/iala/identifiers/advice.rb +1 -1
- data/lib/pubid/iala/identifiers/annex.rb +14 -12
- data/lib/pubid/iala/identifiers/general_assembly.rb +5 -2
- data/lib/pubid/iala/identifiers/guideline.rb +3 -1
- data/lib/pubid/iala/identifiers/letter.rb +1 -1
- data/lib/pubid/iala/identifiers/manual.rb +3 -1
- data/lib/pubid/iala/identifiers/model_course.rb +3 -1
- data/lib/pubid/iala/identifiers/recommendation.rb +3 -1
- data/lib/pubid/iala/identifiers/report.rb +1 -1
- data/lib/pubid/iala/identifiers/resolution.rb +1 -1
- data/lib/pubid/iala/identifiers/standard.rb +3 -1
- data/lib/pubid/iala/identifiers.rb +0 -1
- data/lib/pubid/iala/renderer.rb +1 -1
- data/lib/pubid/iala/urn_generator.rb +1 -1
- data/lib/pubid/iala/urn_parser.rb +19 -2
- data/lib/pubid/iala.rb +4 -4
- data/lib/pubid/iana/builder.rb +20 -0
- data/lib/pubid/iana/identifier.rb +72 -0
- data/lib/pubid/iana/identifiers/registry.rb +33 -0
- data/lib/pubid/iana/identifiers.rb +9 -0
- data/lib/pubid/iana/parser.rb +38 -0
- data/lib/pubid/iana/renderer.rb +29 -0
- data/lib/pubid/iana/urn_generator.rb +15 -0
- data/lib/pubid/iana/urn_parser.rb +24 -0
- data/lib/pubid/iana.rb +69 -0
- data/lib/pubid/identifier.rb +210 -23
- data/lib/pubid/idf/builder.rb +1 -1
- data/lib/pubid/idf/parser.rb +2 -2
- data/lib/pubid/idf/renderer.rb +1 -1
- data/lib/pubid/idf/supplement_identifier.rb +3 -3
- data/lib/pubid/iec/builder.rb +35 -25
- data/lib/pubid/iec/identifier.rb +47 -2
- data/lib/pubid/iec/identifiers/base.rb +2 -2
- data/lib/pubid/iec/identifiers/consolidated_identifier.rb +6 -0
- data/lib/pubid/iec/identifiers/fragment_identifier.rb +11 -11
- data/lib/pubid/iec/identifiers/international_standard.rb +8 -5
- data/lib/pubid/iec/identifiers/sheet_identifier.rb +12 -12
- data/lib/pubid/iec/identifiers/technical_group.rb +30 -0
- data/lib/pubid/iec/identifiers/technical_report.rb +1 -1
- data/lib/pubid/iec/identifiers/technical_specification.rb +1 -1
- data/lib/pubid/iec/identifiers/vap_identifier.rb +12 -12
- data/lib/pubid/iec/identifiers.rb +1 -0
- data/lib/pubid/iec/parser.rb +51 -10
- data/lib/pubid/iec/renderer.rb +18 -8
- data/lib/pubid/iec/single_identifier.rb +1 -1
- data/lib/pubid/iec/supplement_identifier.rb +32 -19
- data/lib/pubid/iec.rb +1 -6
- data/lib/pubid/ieee/aiee/builder.rb +17 -3
- data/lib/pubid/ieee/aiee/identifier.rb +45 -61
- data/lib/pubid/ieee/builder.rb +341 -68
- data/lib/pubid/ieee/compaction.rb +121 -0
- data/lib/pubid/ieee/components/draft.rb +47 -7
- data/lib/pubid/ieee/identifier.rb +1 -3
- data/lib/pubid/ieee/identifiers/adopted_standard.rb +30 -5
- data/lib/pubid/ieee/identifiers/amendment.rb +40 -0
- data/lib/pubid/ieee/identifiers/base.rb +106 -13
- data/lib/pubid/ieee/identifiers/code_number.rb +82 -0
- data/lib/pubid/ieee/identifiers/conformance_identifier.rb +6 -2
- data/lib/pubid/ieee/identifiers/corrigendum.rb +17 -2
- data/lib/pubid/ieee/identifiers/csa_dual_published.rb +3 -3
- data/lib/pubid/ieee/identifiers/dual_identifier.rb +3 -3
- data/lib/pubid/ieee/identifiers/dual_published.rb +3 -3
- data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +102 -5
- data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +2 -1
- data/lib/pubid/ieee/identifiers/joint_development.rb +56 -11
- data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +1 -1
- data/lib/pubid/ieee/identifiers/nesc/base.rb +90 -19
- data/lib/pubid/ieee/identifiers/nesc/draft.rb +20 -5
- data/lib/pubid/ieee/identifiers/nesc/edition.rb +32 -0
- data/lib/pubid/ieee/identifiers/nesc/handbook.rb +16 -5
- data/lib/pubid/ieee/identifiers/nesc/redline.rb +11 -2
- data/lib/pubid/ieee/identifiers/nesc/standard.rb +18 -3
- data/lib/pubid/ieee/identifiers/nesc.rb +1 -0
- data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +3 -3
- data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +14 -6
- data/lib/pubid/ieee/identifiers/redlined_standard.rb +4 -4
- data/lib/pubid/ieee/identifiers/si_standard.rb +4 -1
- data/lib/pubid/ieee/identifiers/standard.rb +4 -1
- data/lib/pubid/ieee/identifiers/supplement_identifier.rb +26 -7
- data/lib/pubid/ieee/identifiers.rb +2 -1
- data/lib/pubid/ieee/ire/builder.rb +7 -6
- data/lib/pubid/ieee/ire/identifier.rb +48 -33
- data/lib/pubid/ieee/nesc/builder.rb +33 -20
- data/lib/pubid/ieee/nesc/parser.rb +15 -14
- data/lib/pubid/ieee/parser.rb +461 -43
- data/lib/pubid/ieee/pre_parser.rb +1 -1
- data/lib/pubid/ieee/renderer.rb +154 -57
- data/lib/pubid/ieee/typed_stages.rb +12 -1
- data/lib/pubid/ieee/urn_generator.rb +3 -5
- data/lib/pubid/ieee.rb +56 -3
- data/lib/pubid/ietf/builder.rb +62 -0
- data/lib/pubid/ietf/identifier.rb +5 -0
- data/lib/pubid/ietf/identifiers/base.rb +75 -0
- data/lib/pubid/ietf/identifiers/bcp.rb +25 -0
- data/lib/pubid/ietf/identifiers/fyi.rb +25 -0
- data/lib/pubid/ietf/identifiers/internet_draft.rb +29 -0
- data/lib/pubid/ietf/identifiers/rfc.rb +25 -0
- data/lib/pubid/ietf/identifiers/std.rb +25 -0
- data/lib/pubid/ietf/identifiers.rb +13 -0
- data/lib/pubid/ietf/parser.rb +43 -0
- data/lib/pubid/ietf/renderer.rb +26 -0
- data/lib/pubid/ietf/urn_generator.rb +23 -0
- data/lib/pubid/ietf/urn_parser.rb +35 -0
- data/lib/pubid/ietf.rb +76 -0
- data/lib/pubid/iho/identifier.rb +1 -3
- data/lib/pubid/iho/identifiers/base.rb +1 -7
- data/lib/pubid/iho/identifiers/bibliographic.rb +1 -1
- data/lib/pubid/iho/identifiers/circular_letter.rb +1 -1
- data/lib/pubid/iho/identifiers/miscellaneous.rb +1 -1
- data/lib/pubid/iho/identifiers/publication.rb +1 -1
- data/lib/pubid/iho/identifiers/standard.rb +1 -1
- data/lib/pubid/iho/identifiers.rb +0 -1
- data/lib/pubid/iho.rb +7 -7
- data/lib/pubid/isbn/builder.rb +44 -0
- data/lib/pubid/isbn/check_digit.rb +53 -0
- data/lib/pubid/isbn/identifier.rb +63 -0
- data/lib/pubid/isbn/identifiers/book.rb +30 -0
- data/lib/pubid/isbn/identifiers.rb +9 -0
- data/lib/pubid/isbn/parser.rb +45 -0
- data/lib/pubid/isbn/renderer.rb +16 -0
- data/lib/pubid/isbn.rb +52 -0
- data/lib/pubid/iso/builder.rb +9 -4
- data/lib/pubid/iso/combined_identifier.rb +2 -2
- data/lib/pubid/iso/identifier.rb +17 -1
- data/lib/pubid/iso/identifiers/directives_supplement.rb +8 -8
- data/lib/pubid/iso/normalizer.rb +2 -2
- data/lib/pubid/iso/parser.rb +16 -12
- data/lib/pubid/iso/supplement_identifier.rb +19 -6
- data/lib/pubid/iso/urn_generator.rb +4 -1
- data/lib/pubid/iso/urn_parser.rb +1 -1
- data/lib/pubid/itu/builder.rb +230 -29
- data/lib/pubid/itu/components/code.rb +48 -5
- data/lib/pubid/itu/components/designation.rb +35 -0
- data/lib/pubid/itu/components.rb +1 -0
- data/lib/pubid/itu/identifier.rb +1 -3
- data/lib/pubid/itu/identifiers/addendum.rb +15 -0
- data/lib/pubid/itu/identifiers/amendment.rb +6 -28
- data/lib/pubid/itu/identifiers/annex.rb +13 -2
- data/lib/pubid/itu/identifiers/annex_of_recommendation.rb +87 -0
- data/lib/pubid/itu/identifiers/appendix_of_recommendation.rb +92 -0
- data/lib/pubid/itu/identifiers/base.rb +341 -23
- data/lib/pubid/itu/identifiers/combined_identifier.rb +99 -23
- data/lib/pubid/itu/identifiers/corrigendum.rb +16 -23
- data/lib/pubid/itu/identifiers/errata.rb +15 -0
- data/lib/pubid/itu/identifiers/handbook.rb +38 -0
- data/lib/pubid/itu/identifiers/question.rb +63 -0
- data/lib/pubid/itu/identifiers/recommendation.rb +3 -2
- data/lib/pubid/itu/identifiers/report.rb +39 -0
- data/lib/pubid/itu/identifiers/special_publication.rb +3 -1
- data/lib/pubid/itu/identifiers/standard_serialization.rb +58 -0
- data/lib/pubid/itu/identifiers/supplement.rb +119 -14
- data/lib/pubid/itu/identifiers.rb +10 -1
- data/lib/pubid/itu/model.rb +1 -1
- data/lib/pubid/itu/parser.rb +480 -26
- data/lib/pubid/itu/urn_generator.rb +36 -6
- data/lib/pubid/itu/urn_parser.rb +8 -0
- data/lib/pubid/itu.rb +11 -3
- data/lib/pubid/jcgm/builder.rb +23 -13
- data/lib/pubid/jcgm/identifiers/amendment.rb +0 -2
- data/lib/pubid/jcgm/identifiers/corrigendum.rb +34 -0
- data/lib/pubid/jcgm/identifiers/gum_guide.rb +3 -3
- data/lib/pubid/jcgm/identifiers/meeting.rb +47 -0
- data/lib/pubid/jcgm/identifiers.rb +2 -0
- data/lib/pubid/jcgm/parser.rb +66 -6
- data/lib/pubid/jcgm/renderer.rb +26 -12
- data/lib/pubid/jcgm/single_identifier.rb +74 -5
- data/lib/pubid/jcgm/supplement_identifier.rb +39 -4
- data/lib/pubid/jcgm/urn_generator.rb +21 -13
- data/lib/pubid/jcgm/urn_parser.rb +15 -3
- data/lib/pubid/jis/identifier.rb +52 -0
- data/lib/pubid/nist/builder.rb +29 -9
- data/lib/pubid/nist/caster.rb +7 -45
- data/lib/pubid/nist/circular_supplement_builder.rb +7 -5
- data/lib/pubid/nist/components/supplement.rb +5 -2
- data/lib/pubid/nist/configuration.rb +7 -1
- data/lib/pubid/nist/identifier.rb +1 -3
- data/lib/pubid/nist/identifiers/base.rb +121 -37
- data/lib/pubid/nist/identifiers/circular.rb +1 -1
- data/lib/pubid/nist/identifiers/commercial_standard.rb +1 -1
- data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +1 -1
- data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +1 -1
- data/lib/pubid/nist/identifiers/crpl_report.rb +1 -1
- data/lib/pubid/nist/identifiers/dated_document.rb +1 -1
- data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +1 -1
- data/lib/pubid/nist/identifiers/grant_contractor_report.rb +1 -1
- data/lib/pubid/nist/identifiers/handbook.rb +1 -1
- data/lib/pubid/nist/identifiers/internal_report.rb +1 -1
- data/lib/pubid/nist/identifiers/letter_circular.rb +1 -1
- data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +1 -1
- data/lib/pubid/nist/identifiers/monograph.rb +1 -1
- data/lib/pubid/nist/identifiers/ncstar.rb +2 -2
- data/lib/pubid/nist/identifiers/nsrds.rb +1 -1
- data/lib/pubid/nist/identifiers/owmwp.rb +1 -1
- data/lib/pubid/nist/identifiers/report.rb +1 -1
- data/lib/pubid/nist/identifiers/special_publication.rb +10 -1
- data/lib/pubid/nist/identifiers/technical_note.rb +1 -1
- data/lib/pubid/nist/identifiers.rb +0 -1
- data/lib/pubid/nist/parser.rb +29 -4
- data/lib/pubid/nist/preprocessor.rb +15 -0
- data/lib/pubid/nist/router.rb +3 -2
- data/lib/pubid/nist/series/ir.rb +0 -3
- data/lib/pubid/nist/supplement_identifier.rb +9 -9
- data/lib/pubid/nist.rb +13 -12
- data/lib/pubid/oasis/builder.rb +77 -0
- data/lib/pubid/oasis/identifier.rb +82 -0
- data/lib/pubid/oasis/identifiers/standard.rb +29 -0
- data/lib/pubid/oasis/identifiers.rb +9 -0
- data/lib/pubid/oasis/parser.rb +34 -0
- data/lib/pubid/oasis/renderer.rb +29 -0
- data/lib/pubid/oasis/urn_generator.rb +25 -0
- data/lib/pubid/oasis/urn_parser.rb +22 -0
- data/lib/pubid/oasis.rb +74 -0
- data/lib/pubid/ogc/builder.rb +33 -0
- data/lib/pubid/ogc/identifier.rb +77 -0
- data/lib/pubid/ogc/identifiers/document.rb +26 -0
- data/lib/pubid/ogc/identifiers.rb +10 -0
- data/lib/pubid/ogc/parser.rb +40 -0
- data/lib/pubid/ogc/renderer.rb +33 -0
- data/lib/pubid/ogc/urn_generator.rb +14 -0
- data/lib/pubid/ogc/urn_parser.rb +22 -0
- data/lib/pubid/ogc.rb +71 -0
- data/lib/pubid/oiml/builder.rb +31 -7
- data/lib/pubid/oiml/identifier.rb +9 -1
- data/lib/pubid/oiml/parser.rb +11 -12
- data/lib/pubid/oiml/renderer.rb +13 -13
- data/lib/pubid/oiml/single_identifier.rb +20 -0
- data/lib/pubid/oiml/supplement_identifier.rb +9 -9
- data/lib/pubid/oiml/urn_parser.rb +23 -6
- data/lib/pubid/oiml.rb +4 -0
- data/lib/pubid/omg/builder.rb +19 -0
- data/lib/pubid/omg/identifier.rb +44 -0
- data/lib/pubid/omg/identifiers/specification.rb +32 -0
- data/lib/pubid/omg/identifiers.rb +9 -0
- data/lib/pubid/omg/parser.rb +40 -0
- data/lib/pubid/omg/renderer.rb +19 -0
- data/lib/pubid/omg.rb +51 -0
- data/lib/pubid/parsers/mr_string.rb +101 -7
- data/lib/pubid/plateau/builder.rb +8 -4
- data/lib/pubid/plateau/identifier.rb +1 -3
- data/lib/pubid/plateau/identifiers/base.rb +1 -6
- data/lib/pubid/plateau/identifiers/handbook.rb +1 -1
- data/lib/pubid/plateau/identifiers/technical_report.rb +1 -1
- data/lib/pubid/plateau/identifiers.rb +0 -1
- data/lib/pubid/plateau/parser.rb +15 -5
- data/lib/pubid/plateau/renderer.rb +1 -1
- data/lib/pubid/plateau/supplement_identifier.rb +11 -11
- data/lib/pubid/plateau.rb +4 -4
- data/lib/pubid/renderers/human_readable.rb +3 -1
- data/lib/pubid/renderers/mr_string.rb +46 -4
- data/lib/pubid/renderers/supplement_renderer.rb +1 -1
- data/lib/pubid/rendering/supplement.rb +4 -4
- data/lib/pubid/sae/builder.rb +1 -1
- data/lib/pubid/sae/identifier.rb +1 -3
- data/lib/pubid/sae/identifiers/base.rb +10 -7
- data/lib/pubid/sae/identifiers.rb +0 -1
- data/lib/pubid/sae.rb +3 -3
- data/lib/pubid/tgpp/builder.rb +41 -0
- data/lib/pubid/tgpp/identifier.rb +91 -0
- data/lib/pubid/tgpp/identifiers/technical_report.rb +32 -0
- data/lib/pubid/tgpp/identifiers/technical_specification.rb +33 -0
- data/lib/pubid/tgpp/identifiers.rb +11 -0
- data/lib/pubid/tgpp/parser.rb +62 -0
- data/lib/pubid/tgpp/renderer.rb +36 -0
- data/lib/pubid/tgpp/urn_generator.rb +20 -0
- data/lib/pubid/tgpp/urn_parser.rb +28 -0
- data/lib/pubid/tgpp.rb +78 -0
- data/lib/pubid/type_resolver.rb +59 -0
- data/lib/pubid/un/builder.rb +42 -0
- data/lib/pubid/un/identifier.rb +37 -0
- data/lib/pubid/un/identifiers/document.rb +24 -0
- data/lib/pubid/un/identifiers.rb +9 -0
- data/lib/pubid/un/parser.rb +25 -0
- data/lib/pubid/un/renderer.rb +11 -0
- data/lib/pubid/un.rb +46 -0
- data/lib/pubid/version.rb +1 -1
- data/lib/pubid/w3c/builder.rb +55 -0
- data/lib/pubid/w3c/identifier.rb +101 -0
- data/lib/pubid/w3c/identifiers/candidate_recommendation.rb +31 -0
- data/lib/pubid/w3c/identifiers/candidate_recommendation_draft.rb +31 -0
- data/lib/pubid/w3c/identifiers/draft_note.rb +31 -0
- data/lib/pubid/w3c/identifiers/note.rb +30 -0
- data/lib/pubid/w3c/identifiers/obsolete_recommendation.rb +31 -0
- data/lib/pubid/w3c/identifiers/proposed_edited_recommendation.rb +31 -0
- data/lib/pubid/w3c/identifiers/proposed_recommendation.rb +31 -0
- data/lib/pubid/w3c/identifiers/recommendation.rb +31 -0
- data/lib/pubid/w3c/identifiers/standard.rb +12 -0
- data/lib/pubid/w3c/identifiers/superseded_recommendation.rb +31 -0
- data/lib/pubid/w3c/identifiers/working_draft.rb +30 -0
- data/lib/pubid/w3c/identifiers.rb +25 -0
- data/lib/pubid/w3c/parser.rb +43 -0
- data/lib/pubid/w3c/renderer.rb +35 -0
- data/lib/pubid/w3c/urn_generator.rb +18 -0
- data/lib/pubid/w3c/urn_parser.rb +36 -0
- data/lib/pubid/w3c.rb +67 -0
- data/lib/pubid/xsf/builder.rb +17 -0
- data/lib/pubid/xsf/identifier.rb +62 -0
- data/lib/pubid/xsf/identifiers/xep.rb +31 -0
- data/lib/pubid/xsf/identifiers.rb +9 -0
- data/lib/pubid/xsf/parser.rb +25 -0
- data/lib/pubid/xsf/renderer.rb +23 -0
- data/lib/pubid/xsf/urn_generator.rb +13 -0
- data/lib/pubid/xsf/urn_parser.rb +18 -0
- data/lib/pubid/xsf.rb +76 -0
- data/lib/pubid.rb +25 -1
- metadata +205 -4
- data/lib/pubid/cie/components/code.rb +0 -80
- data/lib/pubid/iala/identifiers/base.rb +0 -14
|
@@ -6,23 +6,23 @@ module Pubid
|
|
|
6
6
|
# Supplements wrap a base identifier with additional edition information
|
|
7
7
|
#
|
|
8
8
|
# Architecture follows ISO pattern:
|
|
9
|
-
# -
|
|
9
|
+
# - base: The base document being supplemented
|
|
10
10
|
# - edition: Edition information for the supplement
|
|
11
11
|
#
|
|
12
12
|
# Examples:
|
|
13
13
|
# - "NBS CIRC 101e2supp" → CircularSupplement(base: "NBS CIRC 101", edition: e2)
|
|
14
14
|
# - "NBS CIRC 25supp-1924" → CircularSupplement(base: "NBS CIRC 25", edition: 1924)
|
|
15
|
-
class SupplementIdentifier <
|
|
16
|
-
attribute :
|
|
15
|
+
class SupplementIdentifier < Identifier
|
|
16
|
+
attribute :base, Identifier, polymorphic: true
|
|
17
17
|
|
|
18
|
-
# Delegate publisher to
|
|
18
|
+
# Delegate publisher to base
|
|
19
19
|
def publisher
|
|
20
|
-
|
|
20
|
+
base&.publisher
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
# Delegate series to
|
|
23
|
+
# Delegate series to base
|
|
24
24
|
def series
|
|
25
|
-
|
|
25
|
+
base&.series
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def to_s(format = :short)
|
|
@@ -31,9 +31,9 @@ module Pubid
|
|
|
31
31
|
return "NBS CIRC sup#{supplement_date_range_start}-#{supplement_date_range_end}"
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
return super unless
|
|
34
|
+
return super unless base
|
|
35
35
|
|
|
36
|
-
result =
|
|
36
|
+
result = base.to_s(format)
|
|
37
37
|
|
|
38
38
|
# NEW: Handle update attribute (e.g., "Upd12-1926" for supplement patterns)
|
|
39
39
|
if update
|
data/lib/pubid/nist.rb
CHANGED
|
@@ -13,6 +13,7 @@ module Pubid
|
|
|
13
13
|
NIST NBS
|
|
14
14
|
AMS VTS BSS BMS BH FIPS GCR HB MONO MP NCSTAR NSRDS IR SP TN CSWP
|
|
15
15
|
AI CIRC CS CSM CRPL LCIRC OWMWP PC RPT SIBS TIBM TTB EAB JPCRD JRES
|
|
16
|
+
CHIPS NWIRP RB
|
|
16
17
|
].freeze
|
|
17
18
|
|
|
18
19
|
autoload :Builder, "#{__dir__}/nist/builder"
|
|
@@ -20,7 +21,7 @@ module Pubid
|
|
|
20
21
|
autoload :CircularSupplementBuilder, "#{__dir__}/nist/circular_supplement_builder"
|
|
21
22
|
autoload :Components, "#{__dir__}/nist/components"
|
|
22
23
|
autoload :Configuration, "#{__dir__}/nist/configuration"
|
|
23
|
-
autoload :Identifier, "#{__dir__}/nist/
|
|
24
|
+
autoload :Identifier, "#{__dir__}/nist/identifiers/base"
|
|
24
25
|
autoload :Identifiers, "#{__dir__}/nist/identifiers"
|
|
25
26
|
autoload :Parser, "#{__dir__}/nist/parser"
|
|
26
27
|
autoload :ParserOutputNormalizer, "#{__dir__}/nist/parser_output_normalizer"
|
|
@@ -36,7 +37,7 @@ module Pubid
|
|
|
36
37
|
#
|
|
37
38
|
# NIST identifier classes use `typed_stages` (not the `self.type` Hash
|
|
38
39
|
# pattern used by CEN/JCGM/ANSI), so they cannot be auto-discovered.
|
|
39
|
-
#
|
|
40
|
+
# Identifier is the fallback for unmapped series (e.g. AMS, VTS)
|
|
40
41
|
# and must be excluded from typed-stage aggregation.
|
|
41
42
|
IDENTIFIER_TYPES = [
|
|
42
43
|
Identifiers::SpecialPublication,
|
|
@@ -59,12 +60,12 @@ module Pubid
|
|
|
59
60
|
Identifiers::CommercialStandardEmergency,
|
|
60
61
|
Identifiers::CommercialStandardsMonthly,
|
|
61
62
|
Identifiers::DatedDocument,
|
|
62
|
-
|
|
63
|
+
Identifier, # Fallback for unmapped series
|
|
63
64
|
].freeze
|
|
64
65
|
|
|
65
66
|
# Parse a NIST identifier string
|
|
66
67
|
# @param identifier [String] the identifier string to parse
|
|
67
|
-
# @return [
|
|
68
|
+
# @return [Identifier] the parsed identifier
|
|
68
69
|
def self.parse(identifier)
|
|
69
70
|
if identifier.length > Pubid::MAX_INPUT_LENGTH
|
|
70
71
|
raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
|
|
@@ -86,36 +87,36 @@ module Pubid
|
|
|
86
87
|
end
|
|
87
88
|
|
|
88
89
|
# Per-flavor format registry: inherits global formats, overrides :human
|
|
89
|
-
|
|
90
|
-
|
|
90
|
+
Identifier.format_registry = FormatRegistry.new(parent: ::Pubid::Identifier.format_registry)
|
|
91
|
+
Identifier.format_registry.register(:human, renderer: Nist::Renderer)
|
|
91
92
|
|
|
92
93
|
# All identifier classes for external consumption (export, website).
|
|
93
|
-
#
|
|
94
|
+
# Identifier is the fallback for unmapped series and is excluded
|
|
94
95
|
# from external type listings.
|
|
95
96
|
# @return [Array<Class>] identifier classes
|
|
96
97
|
def self.identifier_types
|
|
97
|
-
IDENTIFIER_TYPES.reject { |klass| klass ==
|
|
98
|
+
IDENTIFIER_TYPES.reject { |klass| klass == Identifier }
|
|
98
99
|
end
|
|
99
100
|
|
|
100
101
|
# Aggregate TYPED_STAGES from all identifier classes.
|
|
101
|
-
#
|
|
102
|
+
# Identifier is excluded because it has no typed stages and acts
|
|
102
103
|
# as the fallback for unmapped series.
|
|
103
104
|
# @return [Array<Pubid::Components::TypedStage>] all typed stages
|
|
104
105
|
def self.all_typed_stages
|
|
105
106
|
@all_typed_stages ||= identifier_types
|
|
106
|
-
.reject { |klass| klass ==
|
|
107
|
+
.reject { |klass| klass == Identifier }
|
|
107
108
|
.flat_map(&:typed_stages)
|
|
108
109
|
.freeze
|
|
109
110
|
end
|
|
110
111
|
|
|
111
112
|
# Lookup: type code -> identifier class.
|
|
112
|
-
#
|
|
113
|
+
# Identifier is excluded so it never gets selected by type code.
|
|
113
114
|
# @param code [String, Symbol] the type code to find
|
|
114
115
|
# @return [Class, nil] the matching identifier class, or nil
|
|
115
116
|
def self.locate_type(code)
|
|
116
117
|
type_str = code.to_s
|
|
117
118
|
identifier_types
|
|
118
|
-
.reject { |klass| klass ==
|
|
119
|
+
.reject { |klass| klass == Identifier }
|
|
119
120
|
.find { |klass| klass.typed_stages.any? { |ts| ts.type_code.to_s == type_str } }
|
|
120
121
|
end
|
|
121
122
|
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Oasis
|
|
5
|
+
# Turns the parse tree into an `Identifiers::Standard`: stores the slug
|
|
6
|
+
# verbatim in `original`, then performs a best-effort, ORDER-INDEPENDENT
|
|
7
|
+
# decomposition into spec / version / stage / part / label.
|
|
8
|
+
#
|
|
9
|
+
# Decomposition splits `original` on "-" and classifies each *whole*
|
|
10
|
+
# fragment (so a stage-like substring inside a spec name — e.g. "CSDL" — is
|
|
11
|
+
# never mistaken for a stage). `spec` is the run of leading name fragments
|
|
12
|
+
# before the first recognized fragment; `version`/`stage`/`part` are the
|
|
13
|
+
# first fragment of each recognized kind; `label` is any name fragment
|
|
14
|
+
# appearing after the first recognized one. Anything the classifier cannot
|
|
15
|
+
# place stays only in `original`, so the printed form always round-trips.
|
|
16
|
+
class Builder
|
|
17
|
+
# A fragment is a version when it is `v?N(.N)+` (e.g. "3.0", "v1.2.1",
|
|
18
|
+
# "V1.0"). Bare integers are deliberately NOT versions (too ambiguous
|
|
19
|
+
# with spec-name tokens).
|
|
20
|
+
VERSION_RE = /\Av?\d+(?:\.\d+)+\z/i
|
|
21
|
+
# OASIS approval-stage tokens (+ optional revision digits). Longest-first
|
|
22
|
+
# so shared prefixes classify correctly (CSPRD/CSD before CS, COS before
|
|
23
|
+
# CS/OS).
|
|
24
|
+
STAGE_RE = /\A(?:CSPRD|CSD|COS|CS|WD|OS|PS|PRD|CD|Errata)\d*\z/
|
|
25
|
+
# Part tokens across the three observed spellings, plus bare "Pt"/"P".
|
|
26
|
+
PART_RE = /\A(?:Part|Pt|part|P)\d*\z/
|
|
27
|
+
|
|
28
|
+
def self.build(parsed_data)
|
|
29
|
+
new.build(parsed_data)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def build(data)
|
|
33
|
+
original = data[:original].to_s
|
|
34
|
+
Identifiers::Standard.new(original: original, **decompose(original))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
# @return [Hash] best-effort { spec:, version:, stage:, part:, label: }.
|
|
40
|
+
# Each fragment is classified once into a [fragment, kind] pair. `spec` is
|
|
41
|
+
# the leading run of name fragments; `label` is any name fragment after
|
|
42
|
+
# the first recognized one; version/stage/part are the first of each kind.
|
|
43
|
+
def decompose(original)
|
|
44
|
+
pairs = original.split("-").map { |f| [f, classify(f)] }
|
|
45
|
+
lead = pairs.take_while { |_, kind| kind.nil? }
|
|
46
|
+
rest = pairs.drop(lead.length)
|
|
47
|
+
{
|
|
48
|
+
spec: names(lead),
|
|
49
|
+
version: first_of(rest, :version),
|
|
50
|
+
stage: first_of(rest, :stage),
|
|
51
|
+
part: first_of(rest, :part),
|
|
52
|
+
label: names(rest),
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @return [Symbol, nil] :version / :stage / :part, or nil for a name token
|
|
57
|
+
def classify(fragment)
|
|
58
|
+
return :version if fragment.match?(VERSION_RE)
|
|
59
|
+
return :stage if fragment.match?(STAGE_RE)
|
|
60
|
+
return :part if fragment.match?(PART_RE)
|
|
61
|
+
|
|
62
|
+
nil
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# First fragment of the given kind among [fragment, kind] pairs, or nil.
|
|
66
|
+
def first_of(pairs, kind)
|
|
67
|
+
pairs.find { |_, k| k == kind }&.first
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Name (unclassified) fragments among the pairs, re-joined, or nil.
|
|
71
|
+
def names(pairs)
|
|
72
|
+
fragments = pairs.select { |_, kind| kind.nil? }.map(&:first)
|
|
73
|
+
fragments.empty? ? nil : fragments.join("-")
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Oasis
|
|
5
|
+
# Base class for every OASIS identifier AND the flavor's parse/create entry
|
|
6
|
+
# point. The single concrete type `Identifiers::Standard` descends from this
|
|
7
|
+
# class, so a parsed OASIS id is an instance of `Pubid::Oasis::Identifier`.
|
|
8
|
+
#
|
|
9
|
+
# OASIS identifiers are free-form slugs with an inconsistent internal
|
|
10
|
+
# structure (spec name + version + approval stage + part + label, in
|
|
11
|
+
# varying order). To guarantee a lossless round-trip we always keep the
|
|
12
|
+
# exact printed slug verbatim in `original` (which alone drives `to_s`); the
|
|
13
|
+
# remaining component fields are a best-effort decomposition for relaton
|
|
14
|
+
# querying and can be nil without ever affecting the rendered string.
|
|
15
|
+
class Identifier < ::Pubid::Identifier
|
|
16
|
+
# The exact slug printed after "OASIS " — always set. Drives `to_s`, so
|
|
17
|
+
# the printed form round-trips verbatim regardless of decomposition.
|
|
18
|
+
attribute :original, :string
|
|
19
|
+
# Best-effort decomposition (any may be nil). `spec`/`label` are plain
|
|
20
|
+
# slug fragments; `version`/`stage`/`part` carry the recognized fragment
|
|
21
|
+
# verbatim (e.g. "3.0", "v1.2.1", "PS01", "Errata01", "Pt8", "Part1").
|
|
22
|
+
attribute :spec, :string
|
|
23
|
+
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
|
+
attribute :stage, :string
|
|
29
|
+
attribute :part, :string
|
|
30
|
+
attribute :label, :string
|
|
31
|
+
|
|
32
|
+
# Polymorphic type map for lutaml::Model key_value (de)serialization: maps
|
|
33
|
+
# the subclass's polymorphic_name to its class name so a stored hash
|
|
34
|
+
# rebuilds the correct identifier type via from_hash.
|
|
35
|
+
OASIS_TYPE_MAP = {
|
|
36
|
+
"pubid:oasis:standard" => "Pubid::Oasis::Identifiers::Standard",
|
|
37
|
+
}.freeze
|
|
38
|
+
|
|
39
|
+
key_value do
|
|
40
|
+
map "_type", to: :_type, polymorphic_map: OASIS_TYPE_MAP
|
|
41
|
+
map "original", to: :original
|
|
42
|
+
map "spec", to: :spec
|
|
43
|
+
map "version", to: :version
|
|
44
|
+
map "stage", to: :stage
|
|
45
|
+
map "part", to: :part
|
|
46
|
+
map "label", to: :label
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Publisher is always "OASIS". A plain constant (not a `publisher` method)
|
|
50
|
+
# so it doesn't shadow the inherited lutaml `publisher` attribute, which
|
|
51
|
+
# would otherwise fail serialization type validation.
|
|
52
|
+
PUBLISHER = "OASIS"
|
|
53
|
+
|
|
54
|
+
attr_reader :with_publisher
|
|
55
|
+
|
|
56
|
+
def to_s(with_publisher: true, **opts)
|
|
57
|
+
@with_publisher = with_publisher
|
|
58
|
+
render(format: :human, **opts)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# from_hash is the shared polymorphic dispatch on Pubid::Identifier;
|
|
62
|
+
# OASIS_TYPE_MAP remains as the key_value polymorphic_map.
|
|
63
|
+
|
|
64
|
+
# Parse an OASIS identifier string into an identifier object
|
|
65
|
+
# @param identifier [String] The OASIS identifier string to parse
|
|
66
|
+
# @return [Identifier] The Standard identifier object
|
|
67
|
+
# @raise [RuntimeError] If parsing fails
|
|
68
|
+
def self.parse(identifier)
|
|
69
|
+
# Reject pathological inputs before they reach the parser
|
|
70
|
+
# (CodeQL rb/polynomial-redos barrier — inline .length by design).
|
|
71
|
+
if identifier.length > Pubid::MAX_INPUT_LENGTH
|
|
72
|
+
raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
parsed = Parser.parse(identifier)
|
|
76
|
+
Builder.build(parsed)
|
|
77
|
+
rescue Parslet::ParseFailed => e
|
|
78
|
+
raise "Failed to parse OASIS identifier '#{identifier}': #{e.message}"
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Oasis
|
|
5
|
+
module Identifiers
|
|
6
|
+
# The sole OASIS identifier type. OASIS records carry no document-type
|
|
7
|
+
# distinction in the printed id (every record is `type: OASIS`); the
|
|
8
|
+
# approval stage lives in the `stage` component field, not in the class.
|
|
9
|
+
# Example: "OASIS OSLC-CoreShapes-3.0-PS01-Pt8".
|
|
10
|
+
class Standard < Identifier
|
|
11
|
+
TYPED_STAGES = [
|
|
12
|
+
Pubid::Components::TypedStage.new(
|
|
13
|
+
code: :oasis,
|
|
14
|
+
stage_code: :published,
|
|
15
|
+
type_code: :oasis,
|
|
16
|
+
abbr: ["OASIS"],
|
|
17
|
+
name: "OASIS Standard",
|
|
18
|
+
harmonized_stages: [],
|
|
19
|
+
),
|
|
20
|
+
].freeze
|
|
21
|
+
|
|
22
|
+
def self.type
|
|
23
|
+
{ key: :oasis, web: :standard, title: "OASIS Standard",
|
|
24
|
+
short: "OASIS" }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "parslet"
|
|
4
|
+
|
|
5
|
+
module Pubid
|
|
6
|
+
module Oasis
|
|
7
|
+
# Parslet grammar for printed OASIS identifiers, e.g.
|
|
8
|
+
# "OASIS OSLC-CoreShapes-3.0-PS01-Pt8"
|
|
9
|
+
# "OASIS amqp-core"
|
|
10
|
+
#
|
|
11
|
+
# OASIS slugs are free-form with a highly inconsistent internal structure
|
|
12
|
+
# (varying fragment order, three part spellings, mixed case, a few
|
|
13
|
+
# malformed records with spaces or stray characters). The grammar therefore
|
|
14
|
+
# only strips the "OASIS " publisher prefix and captures the remainder
|
|
15
|
+
# verbatim; the spec/version/stage/part/label decomposition is done in the
|
|
16
|
+
# Builder with order-independent fragment classification. Keeping
|
|
17
|
+
# decomposition out of the PEG avoids brittle backtracking and guarantees a
|
|
18
|
+
# lossless round-trip.
|
|
19
|
+
class Parser < Parslet::Parser
|
|
20
|
+
rule(:prefix) { str("OASIS") >> str(" ") }
|
|
21
|
+
|
|
22
|
+
# The whole slug, captured verbatim (any character, incl. spaces / "]").
|
|
23
|
+
rule(:slug) { any.repeat(1).as(:original) }
|
|
24
|
+
|
|
25
|
+
rule(:identifier) { prefix >> slug }
|
|
26
|
+
|
|
27
|
+
rule(:root) { identifier }
|
|
28
|
+
|
|
29
|
+
def self.parse(input)
|
|
30
|
+
new.parse(input)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Oasis
|
|
5
|
+
# Human-readable renderer for OASIS identifiers.
|
|
6
|
+
#
|
|
7
|
+
# Renders the verbatim slug (`original`), prefixed with the "OASIS "
|
|
8
|
+
# publisher token unless `id.with_publisher == false`. Because rendering is
|
|
9
|
+
# a pure echo of `original`, the printed form always round-trips exactly.
|
|
10
|
+
#
|
|
11
|
+
# "OASIS OSLC-CoreShapes-3.0-PS01-Pt8" (with publisher)
|
|
12
|
+
# "OSLC-CoreShapes-3.0-PS01-Pt8" (without)
|
|
13
|
+
class Renderer < ::Pubid::Renderers::Base
|
|
14
|
+
PUBLISHER = "OASIS"
|
|
15
|
+
|
|
16
|
+
def render(context: nil, **opts)
|
|
17
|
+
id = @id
|
|
18
|
+
body = id.original.to_s
|
|
19
|
+
with_publisher?(id) ? "#{PUBLISHER} #{body}" : body
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def with_publisher?(id)
|
|
25
|
+
id.with_publisher != false
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Oasis
|
|
5
|
+
# Emits `urn:oasis:<slug>`, echoing the verbatim `original` as a single URN
|
|
6
|
+
# segment (OASIS slugs never contain ":"). The only characters that occur in
|
|
7
|
+
# real records outside the URN-safe set are the space and a stray "]" (both
|
|
8
|
+
# only in a handful of malformed records); these are percent-encoded so the
|
|
9
|
+
# URN stays well-formed, and UrnParser reverses them exactly.
|
|
10
|
+
#
|
|
11
|
+
# "OASIS amqp-core" -> "urn:oasis:amqp-core"
|
|
12
|
+
# "OASIS OSLC-CM-v1.0-CS01" -> "urn:oasis:OSLC-CM-v1.0-CS01"
|
|
13
|
+
class UrnGenerator < Pubid::UrnGenerator::Base
|
|
14
|
+
# Character -> percent-encoding for the non-URN-safe characters that
|
|
15
|
+
# actually appear in OASIS slugs. Kept explicit (not a blanket URI escape)
|
|
16
|
+
# so clean slugs — dots, hyphens, mixed case — pass through unchanged.
|
|
17
|
+
ENCODE = { " " => "%20", "]" => "%5D" }.freeze
|
|
18
|
+
|
|
19
|
+
def generate
|
|
20
|
+
slug = identifier.original.to_s.gsub(/[ \]]/) { |c| ENCODE[c] }
|
|
21
|
+
"urn:oasis:#{slug}"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Oasis
|
|
5
|
+
# Parses OASIS URNs back into identifiers by reconstructing the printed form
|
|
6
|
+
# and delegating to the flavor's text parser.
|
|
7
|
+
#
|
|
8
|
+
# UrnGenerator emits `urn:oasis:<slug>` (single segment) with the space and
|
|
9
|
+
# "]" characters percent-encoded; reverse exactly those two here.
|
|
10
|
+
#
|
|
11
|
+
# urn:oasis:OSLC-CM-v1.0-CS01 -> OASIS OSLC-CM-v1.0-CS01
|
|
12
|
+
# urn:oasis:amqp-core -> OASIS amqp-core
|
|
13
|
+
class UrnParser < Pubid::UrnParser::Base
|
|
14
|
+
DECODE = { "%20" => " ", "%5D" => "]" }.freeze
|
|
15
|
+
|
|
16
|
+
def parse_urn(urn)
|
|
17
|
+
slug = strip_namespace(urn).gsub(/%20|%5D/, DECODE)
|
|
18
|
+
flavor_parse("OASIS #{slug}")
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/pubid/oasis.rb
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Oasis
|
|
5
|
+
extend Pubid::PrefixesSupport
|
|
6
|
+
|
|
7
|
+
# Sole OASIS publisher token (see the parser's `prefix` rule). Everything
|
|
8
|
+
# after "OASIS " is a free-form slug, so there are no leading type tokens to
|
|
9
|
+
# exclude.
|
|
10
|
+
PREFIXES = ["OASIS"].freeze
|
|
11
|
+
|
|
12
|
+
autoload :Builder, "#{__dir__}/oasis/builder"
|
|
13
|
+
autoload :Identifier, "#{__dir__}/oasis/identifier"
|
|
14
|
+
autoload :Identifiers, "#{__dir__}/oasis/identifiers"
|
|
15
|
+
autoload :Parser, "#{__dir__}/oasis/parser"
|
|
16
|
+
autoload :Renderer, "#{__dir__}/oasis/renderer"
|
|
17
|
+
autoload :UrnGenerator, "#{__dir__}/oasis/urn_generator"
|
|
18
|
+
autoload :UrnParser, "#{__dir__}/oasis/urn_parser"
|
|
19
|
+
|
|
20
|
+
# Parse an OASIS identifier string
|
|
21
|
+
def self.parse(identifier)
|
|
22
|
+
# Reject pathological inputs before they reach the parser
|
|
23
|
+
# (CodeQL rb/polynomial-redos barrier — inline .length by design).
|
|
24
|
+
if identifier.length > Pubid::MAX_INPUT_LENGTH
|
|
25
|
+
raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
Identifier.parse(identifier)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Per-flavor format registry: inherits global formats, overrides :human
|
|
32
|
+
Identifier.format_registry = FormatRegistry.new(parent: Identifier.format_registry)
|
|
33
|
+
Identifier.format_registry.register(:human, renderer: Oasis::Renderer)
|
|
34
|
+
|
|
35
|
+
# Auto-discover all identifier types from the Identifiers namespace
|
|
36
|
+
# @return [Array<Class>] identifier classes that define a self.type Hash
|
|
37
|
+
def self.identifier_types
|
|
38
|
+
@identifier_types ||= Identifiers.constants
|
|
39
|
+
.filter_map { |c| begin; Identifiers.const_get(c); rescue NameError; nil; end }
|
|
40
|
+
.select { |c| c.is_a?(Class) && c.singleton_methods(false).include?(:type) }
|
|
41
|
+
.select { |c| c.type.is_a?(Hash) }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Build typed stage index from identifier types
|
|
45
|
+
# @return [Array<Pubid::Components::TypedStage>] all typed stages
|
|
46
|
+
def self.all_typed_stages
|
|
47
|
+
@all_typed_stages ||= identifier_types.flat_map do |klass|
|
|
48
|
+
if klass.const_defined?(:TYPED_STAGES)
|
|
49
|
+
klass.const_get(:TYPED_STAGES)
|
|
50
|
+
else
|
|
51
|
+
[]
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Lookup: type code -> identifier class
|
|
57
|
+
# @param code [String, Symbol] the type key to find
|
|
58
|
+
# @return [Class, nil] the matching identifier class
|
|
59
|
+
def self.locate_type(code)
|
|
60
|
+
identifier_types.find { |t| t.type[:key].to_s == code.to_s }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Lookup: abbreviation -> typed stage
|
|
64
|
+
# @param abbr [String, Symbol] the abbreviation to find
|
|
65
|
+
# @return [Pubid::Components::TypedStage, nil] the matching typed stage
|
|
66
|
+
def self.locate_stage(abbr)
|
|
67
|
+
abbr_str = abbr.to_s.upcase
|
|
68
|
+
all_typed_stages.find { |s| s.abbr.any? { |a| a.to_s.upcase == abbr_str } }
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Register OASIS flavor with the registry
|
|
74
|
+
Pubid::Registry.register(:oasis, Pubid::Oasis)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Ogc
|
|
5
|
+
# Turns the parse tree into an Ogc::Identifiers::Document. OGC has a single
|
|
6
|
+
# document type, so there is no type dispatch.
|
|
7
|
+
class Builder
|
|
8
|
+
def self.build(parsed_data)
|
|
9
|
+
new.build(parsed_data)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def build(data)
|
|
13
|
+
Identifiers::Document.new(
|
|
14
|
+
year: data[:year].to_s,
|
|
15
|
+
number: data[:number].to_s,
|
|
16
|
+
revision: normalize_revision(data[:revision]),
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
# Normalize the revision suffix to its canonical lowercased form (the
|
|
23
|
+
# shape the relaton index stores, e.g. "R1" -> "r1"). nil when there is
|
|
24
|
+
# no revision.
|
|
25
|
+
def normalize_revision(revision)
|
|
26
|
+
return nil if revision.nil?
|
|
27
|
+
|
|
28
|
+
normalized = revision.to_s.strip.downcase
|
|
29
|
+
normalized.empty? ? nil : normalized
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Ogc
|
|
5
|
+
# Base class for every OGC identifier AND the flavor's parse/create entry
|
|
6
|
+
# point. There is a single concrete type (Identifiers::Document), so this
|
|
7
|
+
# base mostly exists to hold the shared attributes and the polymorphic
|
|
8
|
+
# serialization mapping.
|
|
9
|
+
class Identifier < ::Pubid::Identifier
|
|
10
|
+
# OGC ids are digit-leading (`<yy>-<nnn>`) with no publisher token in the
|
|
11
|
+
# printed form. Everything is kept as a string to preserve zero-padding
|
|
12
|
+
# ("032", not 32) and the exact revision suffix.
|
|
13
|
+
attribute :year, :string # the "<yy>" field, e.g. "24"
|
|
14
|
+
attribute :number, :string # the "<nnn>" field, e.g. "032"
|
|
15
|
+
# Optional revision suffix, stored as the full lowercased token including
|
|
16
|
+
# its separator letter: "r1", "c1", "a", "r3a", "r12a". nil when absent.
|
|
17
|
+
attribute :revision, :string
|
|
18
|
+
|
|
19
|
+
# Polymorphic type map for lutaml::Model key_value (de)serialization: maps
|
|
20
|
+
# the concrete class's polymorphic_name to its class name so a stored hash
|
|
21
|
+
# rebuilds the correct identifier type via from_hash.
|
|
22
|
+
OGC_TYPE_MAP = {
|
|
23
|
+
"pubid:ogc:document" => "Pubid::Ogc::Identifiers::Document",
|
|
24
|
+
}.freeze
|
|
25
|
+
|
|
26
|
+
key_value do
|
|
27
|
+
map "_type", to: :_type, polymorphic_map: OGC_TYPE_MAP
|
|
28
|
+
map "year", to: :year
|
|
29
|
+
map "number", to: :number
|
|
30
|
+
map "revision", to: :revision
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Publisher is always "OGC". A plain constant (not a `publisher` method)
|
|
34
|
+
# so it doesn't shadow the inherited lutaml `publisher` attribute, which
|
|
35
|
+
# would otherwise fail serialization type validation.
|
|
36
|
+
PUBLISHER = "OGC"
|
|
37
|
+
|
|
38
|
+
attr_reader :with_publisher
|
|
39
|
+
|
|
40
|
+
# Basic string representation. Delegates to the human renderer. The
|
|
41
|
+
# printed OGC id carries no publisher token, so with_publisher defaults to
|
|
42
|
+
# false; pass with_publisher: true to prepend "OGC ".
|
|
43
|
+
def to_s(**opts)
|
|
44
|
+
render(format: :human, **opts)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Capture the with_publisher flag on EVERY render call (default false), so
|
|
48
|
+
# it can never leak across calls: a bare render/to_s always renders
|
|
49
|
+
# without the publisher token regardless of a prior with_publisher: true.
|
|
50
|
+
# The base `render` only forwards `:with_edition` to the renderer, so the
|
|
51
|
+
# flag is threaded via this per-call instance write (the renderer reads
|
|
52
|
+
# `id.with_publisher`).
|
|
53
|
+
def render(format: :human, with_publisher: false, **opts)
|
|
54
|
+
@with_publisher = with_publisher
|
|
55
|
+
super(format: format, **opts)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# from_hash is the shared polymorphic dispatch on Pubid::Identifier.
|
|
59
|
+
# OGC_TYPE_MAP remains as the key_value polymorphic_map.
|
|
60
|
+
|
|
61
|
+
# Parse an OGC identifier string into an identifier object.
|
|
62
|
+
# @param identifier [String] The OGC identifier string to parse
|
|
63
|
+
# @return [Identifier] The document identifier object
|
|
64
|
+
# @raise [ArgumentError] If the input exceeds the maximum length
|
|
65
|
+
# @raise [RuntimeError] If parsing fails
|
|
66
|
+
def self.parse(identifier)
|
|
67
|
+
if identifier.length > Pubid::MAX_INPUT_LENGTH
|
|
68
|
+
raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
Builder.build(Parser.parse(identifier))
|
|
72
|
+
rescue Parslet::ParseFailed => e
|
|
73
|
+
raise "Failed to parse OGC identifier '#{identifier}': #{e.message}"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Ogc
|
|
5
|
+
module Identifiers
|
|
6
|
+
# The sole OGC identifier type. An OGC document is numbered
|
|
7
|
+
# `<yy>-<nnn>[<revision>]` with no publisher token in the printed form.
|
|
8
|
+
class Document < Identifier
|
|
9
|
+
TYPED_STAGES = [
|
|
10
|
+
Pubid::Components::TypedStage.new(
|
|
11
|
+
code: :ogc,
|
|
12
|
+
stage_code: :published,
|
|
13
|
+
type_code: :ogc,
|
|
14
|
+
abbr: ["OGC"],
|
|
15
|
+
name: "OGC Document",
|
|
16
|
+
harmonized_stages: [],
|
|
17
|
+
),
|
|
18
|
+
].freeze
|
|
19
|
+
|
|
20
|
+
def self.type
|
|
21
|
+
{ key: :ogc, web: :document, title: "OGC Document", short: "OGC" }
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|