pubid 1.15.17 → 2.0.0.pre.alpha.1
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/LICENSE.txt +1 -1
- data/README.adoc +2041 -53
- data/archived-gems/pubid-ccsds/update_codes.yaml +1 -0
- data/archived-gems/pubid-iec/stages.yaml +129 -0
- data/archived-gems/pubid-iec/update_codes.yaml +67 -0
- data/archived-gems/pubid-ieee/update_codes.yaml +104 -0
- data/archived-gems/pubid-iso/stages.yaml +106 -0
- data/archived-gems/pubid-iso/update_codes.yaml +4 -0
- data/archived-gems/pubid-itu/i18n.yaml +13 -0
- data/archived-gems/pubid-itu/series.yaml +42 -0
- data/archived-gems/pubid-nist/publishers.yaml +6 -0
- data/archived-gems/pubid-nist/series.yaml +121 -0
- data/archived-gems/pubid-nist/stages.yaml +16 -0
- data/archived-gems/pubid-nist/update_codes.yaml +93 -0
- data/archived-gems/pubid-plateau/update_codes.yaml +6 -0
- data/data/ccsds/update_codes.yaml +1 -0
- data/data/iec/update_codes.yaml +67 -0
- data/data/ieee/update_codes.yaml +104 -0
- data/data/iso/update_codes.yaml +21 -0
- data/data/nist/update_codes.yaml +87 -0
- data/data/plateau/update_codes.yaml +6 -0
- data/lib/pubid/amca/builder.rb +176 -0
- data/lib/pubid/amca/identifier.rb +18 -0
- data/lib/pubid/amca/identifiers/base.rb +64 -0
- data/lib/pubid/amca/identifiers/interpretation.rb +51 -0
- data/lib/pubid/amca/identifiers/publication.rb +47 -0
- data/lib/pubid/amca/identifiers/standard.rb +22 -0
- data/lib/pubid/amca/identifiers.rb +12 -0
- data/lib/pubid/amca/parser.rb +153 -0
- data/lib/pubid/amca/scheme.rb +16 -0
- data/lib/pubid/amca/single_identifier.rb +33 -0
- data/lib/pubid/amca/urn_generator.rb +50 -0
- data/lib/pubid/amca.rb +26 -0
- data/lib/pubid/ansi/builder.rb +52 -0
- data/lib/pubid/ansi/identifier.rb +13 -0
- data/lib/pubid/ansi/identifiers/american_national_standard.rb +12 -0
- data/lib/pubid/ansi/identifiers/standard.rb +16 -0
- data/lib/pubid/ansi/identifiers.rb +11 -0
- data/lib/pubid/ansi/parser.rb +91 -0
- data/lib/pubid/ansi/scheme.rb +15 -0
- data/lib/pubid/ansi/single_identifier.rb +45 -0
- data/lib/pubid/ansi/urn_generator.rb +76 -0
- data/lib/pubid/ansi.rb +27 -0
- data/lib/pubid/api/builder.rb +85 -0
- data/lib/pubid/api/components/code.rb +9 -0
- data/lib/pubid/api/identifier.rb +21 -0
- data/lib/pubid/api/identifiers/base.rb +24 -0
- data/lib/pubid/api/identifiers/bulletin.rb +15 -0
- data/lib/pubid/api/identifiers/continuous_operations_standard.rb +15 -0
- data/lib/pubid/api/identifiers/mpms.rb +44 -0
- data/lib/pubid/api/identifiers/publication.rb +15 -0
- data/lib/pubid/api/identifiers/recommended_practice.rb +15 -0
- data/lib/pubid/api/identifiers/specification.rb +15 -0
- data/lib/pubid/api/identifiers/standard.rb +15 -0
- data/lib/pubid/api/identifiers/technical_report.rb +15 -0
- data/lib/pubid/api/identifiers/typeless_standard.rb +27 -0
- data/lib/pubid/api/parser.rb +140 -0
- data/lib/pubid/api/scheme.rb +66 -0
- data/lib/pubid/api/single_identifier.rb +46 -0
- data/lib/pubid/api/urn_generator.rb +41 -0
- data/lib/pubid/api.rb +17 -0
- data/lib/pubid/ashrae/builder.rb +498 -0
- data/lib/pubid/ashrae/identifier.rb +18 -0
- data/lib/pubid/ashrae/identifiers/addenda_package.rb +46 -0
- data/lib/pubid/ashrae/identifiers/addendum.rb +55 -0
- data/lib/pubid/ashrae/identifiers/base.rb +23 -0
- data/lib/pubid/ashrae/identifiers/combined_addenda.rb +51 -0
- data/lib/pubid/ashrae/identifiers/errata.rb +40 -0
- data/lib/pubid/ashrae/identifiers/guideline.rb +38 -0
- data/lib/pubid/ashrae/identifiers/interpretation.rb +39 -0
- data/lib/pubid/ashrae/identifiers/standard.rb +38 -0
- data/lib/pubid/ashrae/identifiers.rb +16 -0
- data/lib/pubid/ashrae/parser.rb +724 -0
- data/lib/pubid/ashrae/scheme.rb +53 -0
- data/lib/pubid/ashrae/single_identifier.rb +23 -0
- data/lib/pubid/ashrae/supplement_identifier.rb +23 -0
- data/lib/pubid/ashrae/urn_generator.rb +59 -0
- data/lib/pubid/ashrae.rb +21 -0
- data/lib/pubid/asme/builder.rb +153 -0
- data/lib/pubid/asme/components/code.rb +18 -0
- data/lib/pubid/asme/identifier.rb +15 -0
- data/lib/pubid/asme/identifiers/base.rb +70 -0
- data/lib/pubid/asme/identifiers/standard.rb +12 -0
- data/lib/pubid/asme/identifiers.rb +10 -0
- data/lib/pubid/asme/parser.rb +308 -0
- data/lib/pubid/asme/scheme.rb +37 -0
- data/lib/pubid/asme/single_identifier.rb +29 -0
- data/lib/pubid/asme/urn_generator.rb +133 -0
- data/lib/pubid/asme.rb +21 -0
- data/lib/pubid/astm/builder.rb +159 -0
- data/lib/pubid/astm/components/code.rb +33 -0
- data/lib/pubid/astm/identifier.rb +15 -0
- data/lib/pubid/astm/identifiers/adjunct.rb +21 -0
- data/lib/pubid/astm/identifiers/base.rb +13 -0
- data/lib/pubid/astm/identifiers/data_series.rb +25 -0
- data/lib/pubid/astm/identifiers/iso_dual_published.rb +74 -0
- data/lib/pubid/astm/identifiers/manual.rb +40 -0
- data/lib/pubid/astm/identifiers/monograph.rb +25 -0
- data/lib/pubid/astm/identifiers/research_report.rb +18 -0
- data/lib/pubid/astm/identifiers/standard.rb +52 -0
- data/lib/pubid/astm/identifiers/technical_report.rb +23 -0
- data/lib/pubid/astm/identifiers/work_in_progress.rb +21 -0
- data/lib/pubid/astm/parser.rb +244 -0
- data/lib/pubid/astm/scheme.rb +55 -0
- data/lib/pubid/astm/single_identifier.rb +25 -0
- data/lib/pubid/astm/urn_generator.rb +99 -0
- data/lib/pubid/astm.rb +38 -0
- data/lib/pubid/bsi/builder.rb +1483 -0
- data/lib/pubid/bsi/components/code.rb +11 -0
- data/lib/pubid/bsi/components/date.rb +11 -0
- data/lib/pubid/bsi/components/publisher.rb +11 -0
- data/lib/pubid/bsi/components/type.rb +11 -0
- data/lib/pubid/bsi/identifier.rb +27 -0
- data/lib/pubid/bsi/identifiers/addendum_document.rb +64 -0
- data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +95 -0
- data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +82 -0
- data/lib/pubid/bsi/identifiers/aerospace_standard.rb +118 -0
- data/lib/pubid/bsi/identifiers/amendment.rb +40 -0
- data/lib/pubid/bsi/identifiers/base.rb +11 -0
- data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +27 -0
- data/lib/pubid/bsi/identifiers/british_standard.rb +33 -0
- data/lib/pubid/bsi/identifiers/bundled_identifier.rb +114 -0
- data/lib/pubid/bsi/identifiers/committee_document.rb +51 -0
- data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +152 -0
- data/lib/pubid/bsi/identifiers/corrigendum.rb +28 -0
- data/lib/pubid/bsi/identifiers/detailed_specification.rb +69 -0
- data/lib/pubid/bsi/identifiers/disc.rb +56 -0
- data/lib/pubid/bsi/identifiers/draft_document.rb +71 -0
- data/lib/pubid/bsi/identifiers/electronic_book.rb +52 -0
- data/lib/pubid/bsi/identifiers/expert_commentary.rb +47 -0
- data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +82 -0
- data/lib/pubid/bsi/identifiers/flex.rb +61 -0
- data/lib/pubid/bsi/identifiers/handbook.rb +39 -0
- data/lib/pubid/bsi/identifiers/index.rb +62 -0
- data/lib/pubid/bsi/identifiers/method.rb +76 -0
- data/lib/pubid/bsi/identifiers/national_annex.rb +73 -0
- data/lib/pubid/bsi/identifiers/practice_guide.rb +27 -0
- data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +79 -0
- data/lib/pubid/bsi/identifiers/published_document.rb +79 -0
- data/lib/pubid/bsi/identifiers/section.rb +62 -0
- data/lib/pubid/bsi/identifiers/set.rb +46 -0
- data/lib/pubid/bsi/identifiers/standalone_amendment.rb +40 -0
- data/lib/pubid/bsi/identifiers/supplement_document.rb +51 -0
- data/lib/pubid/bsi/identifiers/supplementary_index.rb +81 -0
- data/lib/pubid/bsi/identifiers/technical_specification.rb +79 -0
- data/lib/pubid/bsi/identifiers/test_method.rb +67 -0
- data/lib/pubid/bsi/identifiers/value_added_publication.rb +52 -0
- data/lib/pubid/bsi/identifiers.rb +52 -0
- data/lib/pubid/bsi/model.rb +196 -0
- data/lib/pubid/bsi/parser.rb +659 -0
- data/lib/pubid/bsi/scheme.rb +243 -0
- data/lib/pubid/bsi/single_identifier.rb +129 -0
- data/lib/pubid/bsi/urn_generator.rb +84 -0
- data/lib/pubid/bsi.rb +32 -0
- data/lib/pubid/builder/base.rb +138 -0
- data/lib/pubid/bundled_identifier.rb +126 -0
- data/lib/pubid/ccsds/builder.rb +56 -0
- data/lib/pubid/ccsds/identifier.rb +16 -0
- data/lib/pubid/ccsds/identifiers/base.rb +78 -0
- data/lib/pubid/ccsds/identifiers/base_BASE_88929.rb +70 -0
- data/lib/pubid/ccsds/identifiers/corrigendum.rb +39 -0
- data/lib/pubid/ccsds/identifiers.rb +10 -0
- data/lib/pubid/ccsds/parser.rb +71 -0
- data/lib/pubid/ccsds/scheme.rb +57 -0
- data/lib/pubid/ccsds/single_identifier.rb +74 -0
- data/lib/pubid/ccsds/supplement_identifier.rb +33 -0
- data/lib/pubid/ccsds/urn_generator.rb +115 -0
- data/lib/pubid/ccsds.rb +21 -0
- data/lib/pubid/cen_cenelec/builder.rb +330 -0
- data/lib/pubid/cen_cenelec/identifier.rb +15 -0
- data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +40 -0
- data/lib/pubid/cen_cenelec/identifiers/amendment.rb +29 -0
- data/lib/pubid/cen_cenelec/identifiers/base.rb +75 -0
- data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +28 -0
- data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +27 -0
- data/lib/pubid/cen_cenelec/identifiers/cenelec_harmonization_document.rb +28 -0
- data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +61 -0
- data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +35 -0
- data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +41 -0
- data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +37 -0
- data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +28 -0
- data/lib/pubid/cen_cenelec/identifiers/fragment.rb +22 -0
- data/lib/pubid/cen_cenelec/identifiers/guide.rb +27 -0
- data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +27 -0
- data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +27 -0
- data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +35 -0
- data/lib/pubid/cen_cenelec/identifiers.rb +32 -0
- data/lib/pubid/cen_cenelec/parser.rb +144 -0
- data/lib/pubid/cen_cenelec/scheme.rb +164 -0
- data/lib/pubid/cen_cenelec/single_identifier.rb +130 -0
- data/lib/pubid/cen_cenelec/supplement_identifier.rb +48 -0
- data/lib/pubid/cen_cenelec/urn_generator.rb +129 -0
- data/lib/pubid/cen_cenelec.rb +21 -0
- data/lib/pubid/cie/builder.rb +399 -0
- data/lib/pubid/cie/components/code.rb +72 -0
- data/lib/pubid/cie/components/language.rb +58 -0
- data/lib/pubid/cie/identifier.rb +18 -0
- data/lib/pubid/cie/identifiers/bundle.rb +20 -0
- data/lib/pubid/cie/identifiers/conference.rb +32 -0
- data/lib/pubid/cie/identifiers/corrigendum.rb +40 -0
- data/lib/pubid/cie/identifiers/dual_published.rb +41 -0
- data/lib/pubid/cie/identifiers/identical.rb +64 -0
- data/lib/pubid/cie/identifiers/joint_published.rb +52 -0
- data/lib/pubid/cie/identifiers/standard.rb +58 -0
- data/lib/pubid/cie/identifiers/supplement.rb +45 -0
- data/lib/pubid/cie/identifiers/tutorial_bundle.rb +20 -0
- data/lib/pubid/cie/identifiers.rb +17 -0
- data/lib/pubid/cie/parser.rb +347 -0
- data/lib/pubid/cie/scheme.rb +64 -0
- data/lib/pubid/cie/single_identifier.rb +30 -0
- data/lib/pubid/cie/supplement_identifier.rb +26 -0
- data/lib/pubid/cie/urn_generator.rb +123 -0
- data/lib/pubid/cie.rb +28 -0
- data/lib/pubid/components/code.rb +33 -0
- data/lib/pubid/components/date.rb +49 -0
- data/lib/pubid/components/edition.rb +32 -0
- data/lib/pubid/components/language.rb +37 -0
- data/lib/pubid/components/locality.rb +10 -0
- data/lib/pubid/components/publisher.rb +36 -0
- data/lib/pubid/components/stage.rb +54 -0
- data/lib/pubid/components/type.rb +58 -0
- data/lib/pubid/components/typed_stage.rb +55 -0
- data/lib/pubid/components.rb +15 -0
- data/lib/pubid/core/pattern_doc_generator.rb +272 -0
- data/lib/pubid/core/update_codes.rb +77 -0
- data/lib/pubid/core.rb +8 -0
- data/lib/pubid/csa/builder.rb +671 -0
- data/lib/pubid/csa/components/code.rb +9 -0
- data/lib/pubid/csa/components.rb +9 -0
- data/lib/pubid/csa/composite_identifier.rb +27 -0
- data/lib/pubid/csa/identifier.rb +457 -0
- data/lib/pubid/csa/identifiers/base.rb +133 -0
- data/lib/pubid/csa/identifiers/bundled.rb +125 -0
- data/lib/pubid/csa/identifiers/canadian_adopted.rb +82 -0
- data/lib/pubid/csa/identifiers/cec.rb +129 -0
- data/lib/pubid/csa/identifiers/combined.rb +130 -0
- data/lib/pubid/csa/identifiers/csa_adopted.rb +78 -0
- data/lib/pubid/csa/identifiers/package.rb +65 -0
- data/lib/pubid/csa/identifiers/series.rb +127 -0
- data/lib/pubid/csa/identifiers/standard.rb +10 -0
- data/lib/pubid/csa/identifiers.rb +17 -0
- data/lib/pubid/csa/parser.rb +445 -0
- data/lib/pubid/csa/scheme.rb +44 -0
- data/lib/pubid/csa/single_identifier.rb +30 -0
- data/lib/pubid/csa/urn_generator.rb +80 -0
- data/lib/pubid/csa/wrapper_identifier.rb +31 -0
- data/lib/pubid/csa.rb +25 -0
- data/lib/pubid/etsi/builder.rb +133 -0
- data/lib/pubid/etsi/components/code.rb +42 -0
- data/lib/pubid/etsi/components/version.rb +37 -0
- data/lib/pubid/etsi/components.rb +10 -0
- data/lib/pubid/etsi/identifier.rb +14 -0
- data/lib/pubid/etsi/identifiers/amendment.rb +15 -0
- data/lib/pubid/etsi/identifiers/base.rb +38 -0
- data/lib/pubid/etsi/identifiers/corrigendum.rb +15 -0
- data/lib/pubid/etsi/identifiers/etsi_standard.rb +19 -0
- data/lib/pubid/etsi/identifiers/supplement_identifier.rb +91 -0
- data/lib/pubid/etsi/identifiers.rb +14 -0
- data/lib/pubid/etsi/parser.rb +133 -0
- data/lib/pubid/etsi/scheme.rb +42 -0
- data/lib/pubid/etsi/urn_generator.rb +76 -0
- data/lib/pubid/etsi.rb +21 -0
- data/lib/pubid/export/auditor.rb +89 -0
- data/lib/pubid/export/data_class_exporter.rb +59 -0
- data/lib/pubid/export/exporter.rb +74 -0
- data/lib/pubid/export/flavor_exporter.rb +402 -0
- data/lib/pubid/export/ieee_exporter.rb +78 -0
- data/lib/pubid/export/itu_exporter.rb +66 -0
- data/lib/pubid/export/nist_exporter.rb +64 -0
- data/lib/pubid/export/registry_exporter.rb +90 -0
- data/lib/pubid/export/result.rb +97 -0
- data/lib/pubid/export/scheme_exporter.rb +70 -0
- data/lib/pubid/export.rb +18 -0
- data/lib/pubid/format_detector.rb +16 -0
- data/lib/pubid/format_registry.rb +42 -0
- data/lib/pubid/identifier.rb +235 -0
- data/lib/pubid/identifier_metadata.rb +148 -0
- data/lib/pubid/identifier_registry.rb +198 -0
- data/lib/pubid/idf/builder.rb +82 -0
- data/lib/pubid/idf/identifier.rb +69 -0
- data/lib/pubid/idf/identifiers/amendment.rb +27 -0
- data/lib/pubid/idf/identifiers/corrigendum.rb +27 -0
- data/lib/pubid/idf/identifiers/international_standard.rb +123 -0
- data/lib/pubid/idf/identifiers/reviewed_method.rb +100 -0
- data/lib/pubid/idf/identifiers.rb +13 -0
- data/lib/pubid/idf/parser.rb +143 -0
- data/lib/pubid/idf/scheme.rb +61 -0
- data/lib/pubid/idf/single_identifier.rb +19 -0
- data/lib/pubid/idf/supplement_identifier.rb +43 -0
- data/lib/pubid/idf/urn_generator.rb +84 -0
- data/lib/pubid/idf.rb +25 -0
- data/lib/pubid/iec/builder.rb +457 -0
- data/lib/pubid/iec/components/code.rb +59 -0
- data/lib/pubid/iec/components/consolidated_amendment.rb +59 -0
- data/lib/pubid/iec/components/publisher.rb +35 -0
- data/lib/pubid/iec/components/sheet.rb +32 -0
- data/lib/pubid/iec/components/trf_info.rb +38 -0
- data/lib/pubid/iec/components/vap_suffix.rb +41 -0
- data/lib/pubid/iec/identifier.rb +21 -0
- data/lib/pubid/iec/identifiers/amendment.rb +94 -0
- data/lib/pubid/iec/identifiers/base.rb +78 -0
- data/lib/pubid/iec/identifiers/component_specification.rb +39 -0
- data/lib/pubid/iec/identifiers/conformity_assessment.rb +39 -0
- data/lib/pubid/iec/identifiers/consolidated_identifier.rb +86 -0
- data/lib/pubid/iec/identifiers/corrigendum.rb +94 -0
- data/lib/pubid/iec/identifiers/fragment_identifier.rb +141 -0
- data/lib/pubid/iec/identifiers/guide.rb +104 -0
- data/lib/pubid/iec/identifiers/international_standard.rb +147 -0
- data/lib/pubid/iec/identifiers/interpretation_sheet.rb +104 -0
- data/lib/pubid/iec/identifiers/operational_document.rb +39 -0
- data/lib/pubid/iec/identifiers/publicly_available_specification.rb +101 -0
- data/lib/pubid/iec/identifiers/sheet_identifier.rb +66 -0
- data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +40 -0
- data/lib/pubid/iec/identifiers/systems_reference_document.rb +40 -0
- data/lib/pubid/iec/identifiers/technical_report.rb +132 -0
- data/lib/pubid/iec/identifiers/technical_specification.rb +132 -0
- data/lib/pubid/iec/identifiers/technology_report.rb +39 -0
- data/lib/pubid/iec/identifiers/test_report_form.rb +78 -0
- data/lib/pubid/iec/identifiers/vap_identifier.rb +77 -0
- data/lib/pubid/iec/identifiers/white_paper.rb +39 -0
- data/lib/pubid/iec/identifiers/working_document.rb +96 -0
- data/lib/pubid/iec/parser.rb +412 -0
- data/lib/pubid/iec/rendering_style.rb +113 -0
- data/lib/pubid/iec/scheme.rb +71 -0
- data/lib/pubid/iec/single_identifier.rb +80 -0
- data/lib/pubid/iec/supplement_identifier.rb +161 -0
- data/lib/pubid/iec/urn_generator.rb +193 -0
- data/lib/pubid/iec/urn_parser.rb +289 -0
- data/lib/pubid/iec.rb +85 -0
- data/lib/pubid/ieee/aiee/builder.rb +71 -0
- data/lib/pubid/ieee/aiee/identifier.rb +105 -0
- data/lib/pubid/ieee/aiee/parser.rb +130 -0
- data/lib/pubid/ieee/aiee.rb +11 -0
- data/lib/pubid/ieee/builder.rb +1237 -0
- data/lib/pubid/ieee/components/code.rb +102 -0
- data/lib/pubid/ieee/components/draft.rb +93 -0
- data/lib/pubid/ieee/components/relationship.rb +157 -0
- data/lib/pubid/ieee/components/typed_stage.rb +100 -0
- data/lib/pubid/ieee/identifier.rb +13 -0
- data/lib/pubid/ieee/identifiers/adopted_standard.rb +33 -0
- data/lib/pubid/ieee/identifiers/base.rb +591 -0
- data/lib/pubid/ieee/identifiers/conformance_identifier.rb +35 -0
- data/lib/pubid/ieee/identifiers/corrigendum.rb +37 -0
- data/lib/pubid/ieee/identifiers/csa_dual_published.rb +51 -0
- data/lib/pubid/ieee/identifiers/dual_identifier.rb +18 -0
- data/lib/pubid/ieee/identifiers/dual_published.rb +28 -0
- data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +27 -0
- data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +34 -0
- data/lib/pubid/ieee/identifiers/joint_development.rb +172 -0
- data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +51 -0
- data/lib/pubid/ieee/identifiers/nesc/base.rb +56 -0
- data/lib/pubid/ieee/identifiers/nesc/draft.rb +28 -0
- data/lib/pubid/ieee/identifiers/nesc/handbook.rb +32 -0
- data/lib/pubid/ieee/identifiers/nesc/redline.rb +26 -0
- data/lib/pubid/ieee/identifiers/nesc/standard.rb +26 -0
- data/lib/pubid/ieee/identifiers/nesc.rb +15 -0
- data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +20 -0
- data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +26 -0
- data/lib/pubid/ieee/identifiers/redlined_standard.rb +33 -0
- data/lib/pubid/ieee/identifiers/si_standard.rb +73 -0
- data/lib/pubid/ieee/identifiers/standard.rb +41 -0
- data/lib/pubid/ieee/identifiers/supplement_identifier.rb +23 -0
- data/lib/pubid/ieee/identifiers.rb +33 -0
- data/lib/pubid/ieee/ire/builder.rb +61 -0
- data/lib/pubid/ieee/ire/identifier.rb +58 -0
- data/lib/pubid/ieee/ire/parser.rb +91 -0
- data/lib/pubid/ieee/ire.rb +11 -0
- data/lib/pubid/ieee/nesc/builder.rb +101 -0
- data/lib/pubid/ieee/nesc/parser.rb +154 -0
- data/lib/pubid/ieee/nesc.rb +10 -0
- data/lib/pubid/ieee/parser.rb +1226 -0
- data/lib/pubid/ieee/scheme.rb +90 -0
- data/lib/pubid/ieee/typed_stages.rb +172 -0
- data/lib/pubid/ieee/urn_generator.rb +188 -0
- data/lib/pubid/ieee.rb +32 -0
- data/lib/pubid/ieee_debug.rb +31 -0
- data/lib/pubid/iho/builder.rb +37 -0
- data/lib/pubid/iho/identifier.rb +19 -0
- data/lib/pubid/iho/identifiers/base.rb +41 -0
- data/lib/pubid/iho/identifiers/bibliographic.rb +20 -0
- data/lib/pubid/iho/identifiers/circular_letter.rb +19 -0
- data/lib/pubid/iho/identifiers/miscellaneous.rb +20 -0
- data/lib/pubid/iho/identifiers/publication.rb +19 -0
- data/lib/pubid/iho/identifiers/standard.rb +19 -0
- data/lib/pubid/iho/identifiers.rb +14 -0
- data/lib/pubid/iho/parser.rb +68 -0
- data/lib/pubid/iho/scheme.rb +29 -0
- data/lib/pubid/iho/urn_generator.rb +29 -0
- data/lib/pubid/iho.rb +21 -0
- data/lib/pubid/iso/builder.rb +305 -0
- data/lib/pubid/iso/bundled_identifier.rb +85 -0
- data/lib/pubid/iso/combined_identifier.rb +22 -0
- data/lib/pubid/iso/components/code.rb +36 -0
- data/lib/pubid/iso/components/publisher.rb +60 -0
- data/lib/pubid/iso/components.rb +12 -0
- data/lib/pubid/iso/format_resolver.rb +45 -0
- data/lib/pubid/iso/identifier.rb +69 -0
- data/lib/pubid/iso/identifiers/addendum.rb +104 -0
- data/lib/pubid/iso/identifiers/amendment.rb +128 -0
- data/lib/pubid/iso/identifiers/base.rb +115 -0
- data/lib/pubid/iso/identifiers/corrigendum.rb +108 -0
- data/lib/pubid/iso/identifiers/data.rb +76 -0
- data/lib/pubid/iso/identifiers/directives.rb +59 -0
- data/lib/pubid/iso/identifiers/directives_supplement.rb +119 -0
- data/lib/pubid/iso/identifiers/extract.rb +30 -0
- data/lib/pubid/iso/identifiers/guide.rb +100 -0
- data/lib/pubid/iso/identifiers/international_standard.rb +168 -0
- data/lib/pubid/iso/identifiers/international_standardized_profile.rb +94 -0
- data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +89 -0
- data/lib/pubid/iso/identifiers/pas.rb +93 -0
- data/lib/pubid/iso/identifiers/recommendation.rb +45 -0
- data/lib/pubid/iso/identifiers/supplement.rb +87 -0
- data/lib/pubid/iso/identifiers/tc_document.rb +108 -0
- data/lib/pubid/iso/identifiers/technical_report.rb +103 -0
- data/lib/pubid/iso/identifiers/technical_specification.rb +102 -0
- data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +95 -0
- data/lib/pubid/iso/identifiers.rb +33 -0
- data/lib/pubid/iso/parser.rb +510 -0
- data/lib/pubid/iso/rendering_style.rb +120 -0
- data/lib/pubid/iso/scheme.rb +187 -0
- data/lib/pubid/iso/single_identifier.rb +61 -0
- data/lib/pubid/iso/supplement_identifier.rb +27 -0
- data/lib/pubid/iso/urn_generator.rb +412 -0
- data/lib/pubid/iso/urn_parser.rb +423 -0
- data/lib/pubid/iso/utilities.rb +86 -0
- data/lib/pubid/iso.rb +50 -0
- data/lib/pubid/itu/builder.rb +171 -0
- data/lib/pubid/itu/components/code.rb +39 -0
- data/lib/pubid/itu/components/sector.rb +35 -0
- data/lib/pubid/itu/components/series.rb +29 -0
- data/lib/pubid/itu/i18n.rb +9 -0
- data/lib/pubid/itu/i18n.yaml +30 -0
- data/lib/pubid/itu/identifier.rb +53 -0
- data/lib/pubid/itu/identifiers/amendment.rb +43 -0
- data/lib/pubid/itu/identifiers/annex.rb +74 -0
- data/lib/pubid/itu/identifiers/base.rb +154 -0
- data/lib/pubid/itu/identifiers/combined_identifier.rb +47 -0
- data/lib/pubid/itu/identifiers/corrigendum.rb +44 -0
- data/lib/pubid/itu/identifiers/recommendation.rb +16 -0
- data/lib/pubid/itu/identifiers/special_publication.rb +31 -0
- data/lib/pubid/itu/identifiers/supplement.rb +46 -0
- data/lib/pubid/itu/identifiers.rb +16 -0
- data/lib/pubid/itu/model.rb +111 -0
- data/lib/pubid/itu/parser.rb +225 -0
- data/lib/pubid/itu/scheme.rb +174 -0
- data/lib/pubid/itu/urn_generator.rb +105 -0
- data/lib/pubid/itu.rb +22 -0
- data/lib/pubid/jcgm/builder.rb +88 -0
- data/lib/pubid/jcgm/components/publisher.rb +20 -0
- data/lib/pubid/jcgm/components.rb +9 -0
- data/lib/pubid/jcgm/identifier.rb +11 -0
- data/lib/pubid/jcgm/identifiers/amendment.rb +35 -0
- data/lib/pubid/jcgm/identifiers/guide.rb +21 -0
- data/lib/pubid/jcgm/identifiers/gum_guide.rb +51 -0
- data/lib/pubid/jcgm/identifiers.rb +11 -0
- data/lib/pubid/jcgm/parser.rb +84 -0
- data/lib/pubid/jcgm/scheme.rb +60 -0
- data/lib/pubid/jcgm/single_identifier.rb +48 -0
- data/lib/pubid/jcgm/supplement_identifier.rb +16 -0
- data/lib/pubid/jcgm/urn_generator.rb +110 -0
- data/lib/pubid/jcgm.rb +31 -0
- data/lib/pubid/jis/builder.rb +124 -0
- data/lib/pubid/jis/components/code.rb +59 -0
- data/lib/pubid/jis/components.rb +9 -0
- data/lib/pubid/jis/identifier.rb +18 -0
- data/lib/pubid/jis/identifiers/amendment.rb +16 -0
- data/lib/pubid/jis/identifiers/base.rb +72 -0
- data/lib/pubid/jis/identifiers/explanation.rb +22 -0
- data/lib/pubid/jis/identifiers/japanese_industrial_standard.rb +16 -0
- data/lib/pubid/jis/identifiers/standard.rb +27 -0
- data/lib/pubid/jis/identifiers/technical_report.rb +31 -0
- data/lib/pubid/jis/identifiers/technical_specification.rb +31 -0
- data/lib/pubid/jis/identifiers.rb +17 -0
- data/lib/pubid/jis/parser.rb +109 -0
- data/lib/pubid/jis/scheme.rb +49 -0
- data/lib/pubid/jis/single_identifier.rb +37 -0
- data/lib/pubid/jis/supplement_identifier.rb +47 -0
- data/lib/pubid/jis/urn_generator.rb +25 -0
- data/lib/pubid/jis.rb +23 -0
- data/lib/pubid/lutaml/no_store_registration.rb +30 -0
- data/lib/pubid/nist/builder.rb +2100 -0
- data/lib/pubid/nist/components/code.rb +38 -0
- data/lib/pubid/nist/components/edition.rb +118 -0
- data/lib/pubid/nist/components/issue_number.rb +28 -0
- data/lib/pubid/nist/components/part.rb +77 -0
- data/lib/pubid/nist/components/publisher.rb +24 -0
- data/lib/pubid/nist/components/stage.rb +53 -0
- data/lib/pubid/nist/components/supplement.rb +121 -0
- data/lib/pubid/nist/components/translation.rb +42 -0
- data/lib/pubid/nist/components/update.rb +103 -0
- data/lib/pubid/nist/components/version.rb +35 -0
- data/lib/pubid/nist/components/volume.rb +32 -0
- data/lib/pubid/nist/components.rb +19 -0
- data/lib/pubid/nist/configuration.rb +77 -0
- data/lib/pubid/nist/identifiers/base.rb +499 -0
- data/lib/pubid/nist/identifiers/circular.rb +68 -0
- data/lib/pubid/nist/identifiers/circular_supplement.rb +50 -0
- data/lib/pubid/nist/identifiers/commercial_standard.rb +41 -0
- data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +56 -0
- data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +56 -0
- data/lib/pubid/nist/identifiers/crpl_report.rb +135 -0
- data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +94 -0
- data/lib/pubid/nist/identifiers/grant_contractor_report.rb +35 -0
- data/lib/pubid/nist/identifiers/handbook.rb +50 -0
- data/lib/pubid/nist/identifiers/internal_report.rb +56 -0
- data/lib/pubid/nist/identifiers/letter_circular.rb +45 -0
- data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +65 -0
- data/lib/pubid/nist/identifiers/monograph.rb +69 -0
- data/lib/pubid/nist/identifiers/ncstar.rb +41 -0
- data/lib/pubid/nist/identifiers/nsrds.rb +41 -0
- data/lib/pubid/nist/identifiers/owmwp.rb +35 -0
- data/lib/pubid/nist/identifiers/report.rb +68 -0
- data/lib/pubid/nist/identifiers/special_publication.rb +36 -0
- data/lib/pubid/nist/identifiers/technical_note.rb +90 -0
- data/lib/pubid/nist/identifiers.rb +33 -0
- data/lib/pubid/nist/parser.rb +1084 -0
- data/lib/pubid/nist/scheme.rb +199 -0
- data/lib/pubid/nist/supplement_identifier.rb +83 -0
- data/lib/pubid/nist/urn_generator.rb +127 -0
- data/lib/pubid/nist.rb +36 -0
- data/lib/pubid/oiml/builder.rb +189 -0
- data/lib/pubid/oiml/components/code.rb +20 -0
- data/lib/pubid/oiml/components.rb +9 -0
- data/lib/pubid/oiml/identifier.rb +11 -0
- data/lib/pubid/oiml/identifiers/amendment.rb +13 -0
- data/lib/pubid/oiml/identifiers/annex.rb +62 -0
- data/lib/pubid/oiml/identifiers/base.rb +36 -0
- data/lib/pubid/oiml/identifiers/basic_publication.rb +13 -0
- data/lib/pubid/oiml/identifiers/document.rb +13 -0
- data/lib/pubid/oiml/identifiers/expert_report.rb +13 -0
- data/lib/pubid/oiml/identifiers/guide.rb +13 -0
- data/lib/pubid/oiml/identifiers/recommendation.rb +13 -0
- data/lib/pubid/oiml/identifiers/seminar_report.rb +13 -0
- data/lib/pubid/oiml/identifiers/vocabulary.rb +13 -0
- data/lib/pubid/oiml/identifiers.rb +18 -0
- data/lib/pubid/oiml/parser.rb +173 -0
- data/lib/pubid/oiml/scheme.rb +46 -0
- data/lib/pubid/oiml/single_identifier.rb +90 -0
- data/lib/pubid/oiml/supplement_identifier.rb +43 -0
- data/lib/pubid/oiml/urn_generator.rb +64 -0
- data/lib/pubid/oiml.rb +26 -0
- data/lib/pubid/parser/common_parse_methods.rb +13 -0
- data/lib/pubid/parser/common_parse_rules.rb +56 -0
- data/lib/pubid/parser.rb +8 -0
- data/lib/pubid/parsers/base.rb +11 -0
- data/lib/pubid/parsers/mr_string.rb +93 -0
- data/lib/pubid/plateau/builder.rb +50 -0
- data/lib/pubid/plateau/identifiers/annex.rb +16 -0
- data/lib/pubid/plateau/identifiers/base.rb +51 -0
- data/lib/pubid/plateau/identifiers/handbook.rb +34 -0
- data/lib/pubid/plateau/identifiers/technical_report.rb +20 -0
- data/lib/pubid/plateau/identifiers.rb +12 -0
- data/lib/pubid/plateau/parser.rb +63 -0
- data/lib/pubid/plateau/scheme.rb +45 -0
- data/lib/pubid/plateau/supplement_identifier.rb +72 -0
- data/lib/pubid/plateau/urn_generator.rb +29 -0
- data/lib/pubid/plateau.rb +25 -0
- data/lib/pubid/renderers/base.rb +19 -0
- data/lib/pubid/renderers/directives_renderer.rb +62 -0
- data/lib/pubid/renderers/guide_renderer.rb +20 -0
- data/lib/pubid/renderers/human_readable.rb +58 -0
- data/lib/pubid/renderers/iwa_renderer.rb +16 -0
- data/lib/pubid/renderers/mr_string.rb +16 -0
- data/lib/pubid/renderers/supplement_renderer.rb +33 -0
- data/lib/pubid/renderers/urn.rb +11 -0
- data/lib/pubid/renderers.rb +14 -0
- data/lib/pubid/rendering/base.rb +73 -0
- data/lib/pubid/rendering/common.rb +211 -0
- data/lib/pubid/rendering/context.rb +156 -0
- data/lib/pubid/rendering/date.rb +27 -0
- data/lib/pubid/rendering/format.rb +25 -0
- data/lib/pubid/rendering/language.rb +21 -0
- data/lib/pubid/rendering/numbering.rb +24 -0
- data/lib/pubid/rendering/publisher.rb +25 -0
- data/lib/pubid/rendering/stage.rb +38 -0
- data/lib/pubid/rendering/supplement.rb +46 -0
- data/lib/pubid/rendering.rb +16 -0
- data/lib/pubid/sae/builder.rb +32 -0
- data/lib/pubid/sae/components/code.rb +9 -0
- data/lib/pubid/sae/components/date.rb +19 -0
- data/lib/pubid/sae/components/type.rb +19 -0
- data/lib/pubid/sae/components.rb +11 -0
- data/lib/pubid/sae/identifier.rb +14 -0
- data/lib/pubid/sae/identifiers/base.rb +42 -0
- data/lib/pubid/sae/identifiers.rb +9 -0
- data/lib/pubid/sae/parser.rb +55 -0
- data/lib/pubid/sae/scheme.rb +47 -0
- data/lib/pubid/sae/urn_generator.rb +38 -0
- data/lib/pubid/sae.rb +19 -0
- data/lib/pubid/scheme.rb +207 -0
- data/lib/pubid/urn_generator/base.rb +110 -0
- data/lib/pubid/utils/string_normalizer.rb +196 -0
- data/lib/pubid/utils.rb +7 -0
- data/lib/pubid/version.rb +3 -1
- data/lib/pubid.rb +137 -13
- data/lib/tasks/docs.rake +37 -0
- data/lib/tasks/export.rake +38 -0
- data/lib/tasks/website-data.json +7488 -0
- metadata +613 -171
- data/lib/pubid/registry.rb +0 -30
|
@@ -0,0 +1,1237 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Ieee
|
|
5
|
+
# Builder class for constructing IEEE identifier scheme from parsed data
|
|
6
|
+
# Single Responsibility: Transform parsed data into Scheme objects
|
|
7
|
+
class Builder
|
|
8
|
+
attr_accessor :original_input
|
|
9
|
+
attr_reader :identifier_class
|
|
10
|
+
|
|
11
|
+
def initialize(identifier_class = Identifiers::Base)
|
|
12
|
+
@identifier_class = identifier_class
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Build a scheme object from parsed data
|
|
16
|
+
# @param parsed [Hash, Array] the parsed identifier data
|
|
17
|
+
# @return [Scheme] the constructed scheme object
|
|
18
|
+
def build(parsed)
|
|
19
|
+
# Handle CSA dual published patterns
|
|
20
|
+
if parsed[:ieee_portion] && parsed[:csa_portion]
|
|
21
|
+
return build_csa_dual_published(parsed)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Handle combined AIEE identifiers (from "Nos X and Y" preprocessing)
|
|
25
|
+
if parsed[:first_aiee] && parsed[:second_aiee]
|
|
26
|
+
return build_combined_aiee(parsed)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Handle dual published patterns
|
|
30
|
+
if parsed[:first] && parsed[:second]
|
|
31
|
+
return build_dual_published(parsed)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Handle IEC/IEEE copublished patterns
|
|
35
|
+
if parsed[:content]
|
|
36
|
+
return build_iec_ieee_copublished(parsed)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Handle NESC identifiers (National Electrical Safety Code)
|
|
40
|
+
if parsed[:nesc]
|
|
41
|
+
nesc_builder = Nesc::Builder.new
|
|
42
|
+
return nesc_builder.build(parsed[:nesc])
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Handle AIEE identifiers (American Institute of Electrical Engineers)
|
|
46
|
+
if parsed[:aiee]
|
|
47
|
+
aiee_builder = Aiee::Builder.new
|
|
48
|
+
return aiee_builder.build(parsed[:aiee])
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Handle IRE identifiers (Institute of Radio Engineers)
|
|
52
|
+
if parsed[:ire]
|
|
53
|
+
ire_builder = Ire::Builder.new
|
|
54
|
+
return ire_builder.build(parsed[:ire])
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Handle IEEE/ASTM SI/PSI identifiers (Système International)
|
|
58
|
+
if parsed[:si_type]
|
|
59
|
+
return build_si_psi_identifier(parsed)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Handle single identifier
|
|
63
|
+
build_single_identifier(parsed)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
# Build IEC/IEEE copublished identifier
|
|
69
|
+
def build_iec_ieee_copublished(parsed)
|
|
70
|
+
content = extract_value(parsed[:content])
|
|
71
|
+
|
|
72
|
+
# Parse the content to extract components
|
|
73
|
+
copublished_number = nil
|
|
74
|
+
draft_info = nil
|
|
75
|
+
iec_year = nil
|
|
76
|
+
date_info = nil
|
|
77
|
+
|
|
78
|
+
if content
|
|
79
|
+
# Extract copublished number (everything before IEC: or comma or parenthesis)
|
|
80
|
+
copublished_number = if content.include?("IEC:")
|
|
81
|
+
content.split(" IEC:").first.strip
|
|
82
|
+
elsif content.include?(", ")
|
|
83
|
+
content.split(", ").first.strip
|
|
84
|
+
elsif content.include?(" (")
|
|
85
|
+
content.split(" (").first.strip
|
|
86
|
+
else
|
|
87
|
+
content.strip
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Extract draft info if present
|
|
91
|
+
if copublished_number.include?("/D")
|
|
92
|
+
parts = copublished_number.split("/D")
|
|
93
|
+
copublished_number = parts[0]
|
|
94
|
+
draft_info = "/D#{parts[1] || ''}"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Extract IEC year if present
|
|
98
|
+
if content.include?("IEC:")
|
|
99
|
+
iec_part = content.split("IEC:")[1]
|
|
100
|
+
if iec_part
|
|
101
|
+
iec_year = iec_part.split.first
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Extract date info if present
|
|
106
|
+
if content.include?(" (")
|
|
107
|
+
date_part = content.split(" (")[1]
|
|
108
|
+
if date_part&.include?(")")
|
|
109
|
+
date_info = date_part.split(")")[0]
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
Identifiers::IecIeeeCopublished.new(
|
|
115
|
+
copublished_number: copublished_number,
|
|
116
|
+
draft_info: draft_info,
|
|
117
|
+
iec_year: iec_year,
|
|
118
|
+
date_info: date_info,
|
|
119
|
+
)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Build dual published identifier
|
|
123
|
+
def build_dual_published(parsed)
|
|
124
|
+
first_id = build_single_identifier(parsed[:first])
|
|
125
|
+
second_id = build_single_identifier(parsed[:second])
|
|
126
|
+
|
|
127
|
+
Identifiers::DualPublished.new(
|
|
128
|
+
first_identifier: first_id,
|
|
129
|
+
second_identifier: second_id,
|
|
130
|
+
)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Build CSA dual published identifier
|
|
134
|
+
# @param parsed [Hash] parsed CSA dual published data
|
|
135
|
+
# @return [Identifiers::CsaDualPublished] CSA dual published identifier
|
|
136
|
+
def build_csa_dual_published(parsed)
|
|
137
|
+
# Build IEEE portion
|
|
138
|
+
ieee_id = build_single_identifier(parsed[:ieee_portion])
|
|
139
|
+
|
|
140
|
+
# Extract and parse CSA portion using CSA parser
|
|
141
|
+
csa_string = extract_value(parsed[:csa_portion])
|
|
142
|
+
|
|
143
|
+
# Prepend "CSA " prefix if not present (CSA parser expects this format)
|
|
144
|
+
csa_string = "CSA #{csa_string}" unless csa_string.start_with?("CSA",
|
|
145
|
+
"CAN/")
|
|
146
|
+
|
|
147
|
+
# Use CSA parser to parse the CSA portion
|
|
148
|
+
csa_id = Pubid::Csa.parse(csa_string)
|
|
149
|
+
|
|
150
|
+
Identifiers::CsaDualPublished.new(
|
|
151
|
+
ieee_identifier: ieee_id,
|
|
152
|
+
csa_identifier: csa_id,
|
|
153
|
+
)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Build single identifier
|
|
157
|
+
def build_single_identifier(parsed, building_secondary: false)
|
|
158
|
+
# Parslet can return array of hashes - merge them
|
|
159
|
+
parsed_hash = parsed.is_a?(Array) ? merge_parsed_array(parsed) : parsed
|
|
160
|
+
|
|
161
|
+
# Handle multi-numbered identifiers (cross-reference and joint standards)
|
|
162
|
+
# CRITICAL: Don't recurse when building secondary identifier to prevent infinite loop
|
|
163
|
+
if !building_secondary && parsed_hash[:primary_identifier] && (parsed_hash[:secondary_crossref] || parsed_hash[:secondary_joint])
|
|
164
|
+
return build_multi_numbered_identifier(parsed_hash)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Handle corrigendum supplements (check for base_identifier + cor_number)
|
|
168
|
+
# This enables recursive base identifier parsing like ISO/IEC Amendment
|
|
169
|
+
if parsed_hash[:base_identifier] && parsed_hash[:cor_number]
|
|
170
|
+
return build_corrigendum_supplement(parsed_hash)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Handle interpretation supplements (check for base_identifier + int_year)
|
|
174
|
+
if parsed_hash[:base_identifier] && (parsed_hash[:int_year] || parsed_hash[:interpretation])
|
|
175
|
+
return build_interpretation_supplement(parsed_hash)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# Handle conformance supplements (check for base_identifier + conf_number)
|
|
179
|
+
if parsed_hash[:base_identifier] && parsed_hash[:conf_number]
|
|
180
|
+
return build_conformance_supplement(parsed_hash)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Handle joint development patterns from parser
|
|
184
|
+
if parsed_hash[:joint_publishers] || parsed_hash[:iso_stage]
|
|
185
|
+
return build_joint_development(parsed_hash)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
attributes = extract_attributes(parsed_hash)
|
|
189
|
+
|
|
190
|
+
# Handle relationships if present (Pattern 4)
|
|
191
|
+
if parsed_hash[:relationship_type] || parsed_hash[:relationship_clause]
|
|
192
|
+
attributes[:relationships] = build_relationships(parsed_hash)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Route to appropriate identifier class based on content
|
|
196
|
+
identifier_class = determine_identifier_class(attributes)
|
|
197
|
+
identifier_class.new(**attributes)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Build corrigendum supplement with recursive base parsing
|
|
201
|
+
# @param parsed_hash [Hash] parsed data with base and supplement info
|
|
202
|
+
# @return [Identifiers::Corrigendum] corrigendum identifier
|
|
203
|
+
def build_corrigendum_supplement(parsed_hash)
|
|
204
|
+
# Reconstruct base identifier string from parsed components
|
|
205
|
+
base_parts = []
|
|
206
|
+
base_data = parsed_hash[:base_identifier]
|
|
207
|
+
|
|
208
|
+
# Extract publisher
|
|
209
|
+
if base_data[:publishers]
|
|
210
|
+
pub_data = base_data[:publishers]
|
|
211
|
+
publisher_str = extract_value(pub_data[:publisher])
|
|
212
|
+
|
|
213
|
+
if pub_data[:copublishers] && !pub_data[:copublishers].empty?
|
|
214
|
+
copubs = pub_data[:copublishers]
|
|
215
|
+
copubs = [copubs] unless copubs.is_a?(Array)
|
|
216
|
+
copub_strs = copubs.filter_map do |cp|
|
|
217
|
+
extract_value(cp[:copublisher])
|
|
218
|
+
end
|
|
219
|
+
publisher_str += "/#{copub_strs.join('/')}" if !copub_strs.empty?
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
base_parts << publisher_str
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# Extract type
|
|
226
|
+
if base_data[:type]
|
|
227
|
+
base_parts << extract_value(base_data[:type])
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# Extract number with parts and year
|
|
231
|
+
# Build the complete code string: "802.1AC-2016" or "535-2013" or "C37.41-2016"
|
|
232
|
+
number_str = extract_value(base_data[:number])
|
|
233
|
+
|
|
234
|
+
# Add part if present (e.g., ".1AC" or ".41")
|
|
235
|
+
if base_data[:part]
|
|
236
|
+
part_val = extract_value(base_data[:part])
|
|
237
|
+
# Determine separator: dot for most cases, dash for some
|
|
238
|
+
separator = number_str.match?(/^[A-Z]/) ? "." : "." # Letter prefix uses dot
|
|
239
|
+
number_str += separator + part_val
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# Add subpart if present
|
|
243
|
+
if base_data[:subpart]
|
|
244
|
+
subparts = base_data[:subpart]
|
|
245
|
+
subparts = [subparts] unless subparts.is_a?(Array)
|
|
246
|
+
subparts.each do |sp|
|
|
247
|
+
subpart_val = extract_value(sp)
|
|
248
|
+
number_str += ".#{subpart_val}" if subpart_val
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# Add year with dash (e.g., "-2016")
|
|
253
|
+
if base_data[:year]
|
|
254
|
+
year_val = extract_value(base_data[:year])
|
|
255
|
+
number_str += "-#{year_val}"
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
base_parts << number_str
|
|
259
|
+
|
|
260
|
+
# Build base string and recursively parse it
|
|
261
|
+
base_string = base_parts.join(" ")
|
|
262
|
+
|
|
263
|
+
# Recursively parse base identifier using Base.parse
|
|
264
|
+
base_identifier = Identifiers::Base.parse(base_string)
|
|
265
|
+
|
|
266
|
+
# Extract corrigendum attributes
|
|
267
|
+
cor_number = extract_value(parsed_hash[:cor_number])
|
|
268
|
+
cor_year = extract_value(parsed_hash[:cor_year])
|
|
269
|
+
|
|
270
|
+
# Create Corrigendum with parsed base
|
|
271
|
+
Identifiers::Corrigendum.new(
|
|
272
|
+
base_identifier: base_identifier,
|
|
273
|
+
cor_number: cor_number,
|
|
274
|
+
cor_year: cor_year,
|
|
275
|
+
)
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# Build interpretation supplement with recursive base parsing
|
|
279
|
+
# @param parsed_hash [Hash] parsed data with base and supplement info
|
|
280
|
+
# @return [Identifiers::InterpretationIdentifier] interpretation identifier
|
|
281
|
+
def build_interpretation_supplement(parsed_hash)
|
|
282
|
+
# Reconstruct base identifier string from parsed components (same logic as corrigendum)
|
|
283
|
+
base_parts = []
|
|
284
|
+
base_data = parsed_hash[:base_identifier]
|
|
285
|
+
|
|
286
|
+
# Extract publisher
|
|
287
|
+
if base_data[:publishers]
|
|
288
|
+
pub_data = base_data[:publishers]
|
|
289
|
+
publisher_str = extract_value(pub_data[:publisher])
|
|
290
|
+
|
|
291
|
+
if pub_data[:copublishers] && !pub_data[:copublishers].empty?
|
|
292
|
+
copubs = pub_data[:copublishers]
|
|
293
|
+
copubs = [copubs] unless copubs.is_a?(Array)
|
|
294
|
+
copub_strs = copubs.filter_map do |cp|
|
|
295
|
+
extract_value(cp[:copublisher])
|
|
296
|
+
end
|
|
297
|
+
publisher_str += "/#{copub_strs.join('/')}" if !copub_strs.empty?
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
base_parts << publisher_str
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
# Extract type
|
|
304
|
+
if base_data[:type]
|
|
305
|
+
base_parts << extract_value(base_data[:type])
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# Extract number with parts and year
|
|
309
|
+
number_str = extract_value(base_data[:number])
|
|
310
|
+
|
|
311
|
+
# Add part if present
|
|
312
|
+
if base_data[:part]
|
|
313
|
+
part_val = extract_value(base_data[:part])
|
|
314
|
+
separator = number_str.match?(/^[A-Z]/) ? "." : "."
|
|
315
|
+
number_str += separator + part_val
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
# Add subpart if present
|
|
319
|
+
if base_data[:subpart]
|
|
320
|
+
subparts = base_data[:subpart]
|
|
321
|
+
subparts = [subparts] unless subparts.is_a?(Array)
|
|
322
|
+
subparts.each do |sp|
|
|
323
|
+
subpart_val = extract_value(sp)
|
|
324
|
+
number_str += ".#{subpart_val}" if subpart_val
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
# Add year with dash
|
|
329
|
+
if base_data[:year]
|
|
330
|
+
year_val = extract_value(base_data[:year])
|
|
331
|
+
number_str += "-#{year_val}"
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
base_parts << number_str
|
|
335
|
+
|
|
336
|
+
# Build base string and recursively parse it
|
|
337
|
+
base_string = base_parts.join(" ")
|
|
338
|
+
|
|
339
|
+
# Recursively parse base identifier using Base.parse
|
|
340
|
+
base_identifier = Identifiers::Base.parse(base_string)
|
|
341
|
+
|
|
342
|
+
# Extract interpretation attributes
|
|
343
|
+
int_year = extract_value(parsed_hash[:int_year])
|
|
344
|
+
|
|
345
|
+
# Create InterpretationIdentifier with parsed base
|
|
346
|
+
Identifiers::InterpretationIdentifier.new(
|
|
347
|
+
base_identifier: base_identifier,
|
|
348
|
+
int_year: int_year,
|
|
349
|
+
)
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# Build conformance supplement with recursive base parsing
|
|
353
|
+
# @param parsed_hash [Hash] parsed data with base and supplement info
|
|
354
|
+
# @return [Identifiers::ConformanceIdentifier] conformance identifier
|
|
355
|
+
def build_conformance_supplement(parsed_hash)
|
|
356
|
+
# Reconstruct base identifier string from parsed components (same logic as corrigendum)
|
|
357
|
+
base_parts = []
|
|
358
|
+
base_data = parsed_hash[:base_identifier]
|
|
359
|
+
|
|
360
|
+
# Extract publisher
|
|
361
|
+
if base_data[:publishers]
|
|
362
|
+
pub_data = base_data[:publishers]
|
|
363
|
+
publisher_str = extract_value(pub_data[:publisher])
|
|
364
|
+
|
|
365
|
+
if pub_data[:copublishers] && !pub_data[:copublishers].empty?
|
|
366
|
+
copubs = pub_data[:copublishers]
|
|
367
|
+
copubs = [copubs] unless copubs.is_a?(Array)
|
|
368
|
+
copub_strs = copubs.filter_map do |cp|
|
|
369
|
+
extract_value(cp[:copublisher])
|
|
370
|
+
end
|
|
371
|
+
publisher_str += "/#{copub_strs.join('/')}" if !copub_strs.empty?
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
base_parts << publisher_str
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
# Extract type
|
|
378
|
+
if base_data[:type]
|
|
379
|
+
base_parts << extract_value(base_data[:type])
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
# Extract number with parts and year
|
|
383
|
+
number_str = extract_value(base_data[:number])
|
|
384
|
+
|
|
385
|
+
# Add part if present
|
|
386
|
+
if base_data[:part]
|
|
387
|
+
part_val = extract_value(base_data[:part])
|
|
388
|
+
separator = number_str.match?(/^[A-Z]/) ? "." : "."
|
|
389
|
+
number_str += separator + part_val
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
# Add subpart if present
|
|
393
|
+
if base_data[:subpart]
|
|
394
|
+
subparts = base_data[:subpart]
|
|
395
|
+
subparts = [subparts] unless subparts.is_a?(Array)
|
|
396
|
+
subparts.each do |sp|
|
|
397
|
+
subpart_val = extract_value(sp)
|
|
398
|
+
number_str += ".#{subpart_val}" if subpart_val
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
# Add year with dash
|
|
403
|
+
if base_data[:year]
|
|
404
|
+
year_val = extract_value(base_data[:year])
|
|
405
|
+
number_str += "-#{year_val}"
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
base_parts << number_str
|
|
409
|
+
|
|
410
|
+
# Build base string and recursively parse it
|
|
411
|
+
base_string = base_parts.join(" ")
|
|
412
|
+
|
|
413
|
+
# Recursively parse base identifier using Base.parse
|
|
414
|
+
base_identifier = Identifiers::Base.parse(base_string)
|
|
415
|
+
|
|
416
|
+
# Extract conformance attributes
|
|
417
|
+
conf_number = extract_value(parsed_hash[:conf_number])
|
|
418
|
+
conf_year = extract_value(parsed_hash[:conf_year])
|
|
419
|
+
|
|
420
|
+
# Create ConformanceIdentifier with parsed base
|
|
421
|
+
Identifiers::ConformanceIdentifier.new(
|
|
422
|
+
base_identifier: base_identifier,
|
|
423
|
+
conf_number: conf_number,
|
|
424
|
+
conf_year: conf_year,
|
|
425
|
+
)
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
# Build joint development identifier from parsed data
|
|
429
|
+
def build_joint_development(parsed)
|
|
430
|
+
attributes = {}
|
|
431
|
+
|
|
432
|
+
# Extract publishers from joint_publishers
|
|
433
|
+
if parsed[:joint_publishers]
|
|
434
|
+
joint_pub_str = extract_value(parsed[:joint_publishers])
|
|
435
|
+
attributes[:publishers] = joint_pub_str.split("/")
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
# Build code with parts if present
|
|
439
|
+
code_parts = []
|
|
440
|
+
code_parts << extract_value(parsed[:part]) if parsed[:part]
|
|
441
|
+
|
|
442
|
+
code_str = extract_value(parsed[:number])
|
|
443
|
+
if code_str && !code_parts.empty?
|
|
444
|
+
code_str += ".#{code_parts.join('.')}"
|
|
445
|
+
end
|
|
446
|
+
attributes[:code] = code_str
|
|
447
|
+
|
|
448
|
+
# Extract year
|
|
449
|
+
attributes[:year] = extract_value(parsed[:year]) if parsed[:year]
|
|
450
|
+
|
|
451
|
+
# Detect lead party based on pattern
|
|
452
|
+
if parsed[:iso_stage]
|
|
453
|
+
# ISO format - lead party is ISO
|
|
454
|
+
attributes[:lead_party] = "ISO"
|
|
455
|
+
attributes[:iso_stage] = extract_value(parsed[:iso_stage])
|
|
456
|
+
|
|
457
|
+
# Create typed_stage for ISO stage
|
|
458
|
+
stage_abbr = attributes[:iso_stage]
|
|
459
|
+
if stage_abbr
|
|
460
|
+
attributes[:typed_stage] =
|
|
461
|
+
Ieee::Scheme.locate_typed_stage_by_abbr(stage_abbr)
|
|
462
|
+
end
|
|
463
|
+
else
|
|
464
|
+
# IEEE format - lead party is IEEE
|
|
465
|
+
attributes[:lead_party] = "IEEE"
|
|
466
|
+
|
|
467
|
+
# Extract draft version if present (e.g., D8 from /D8)
|
|
468
|
+
if parsed[:draft_version]
|
|
469
|
+
draft_ver = extract_value(parsed[:draft_version])
|
|
470
|
+
# Remove leading 'D' if present since draft_version already has it
|
|
471
|
+
draft_ver = draft_ver.sub(/^D/, "") if draft_ver
|
|
472
|
+
attributes[:ieee_draft] = "D#{draft_ver}" if draft_ver
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
# Mark as project (P prefix)
|
|
476
|
+
attributes[:type] = "P"
|
|
477
|
+
|
|
478
|
+
# Create typed_stage for IEEE project
|
|
479
|
+
attributes[:typed_stage] =
|
|
480
|
+
Ieee::Scheme.locate_typed_stage_by_abbr("P")
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
Identifiers::JointDevelopment.new(**attributes)
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
# Build SI/PSI identifier from parsed data
|
|
487
|
+
# @param parsed [Hash] parsed SI/PSI data
|
|
488
|
+
# @return [Identifiers::SiStandard] SI or PSI identifier (both use same class)
|
|
489
|
+
def build_si_psi_identifier(parsed)
|
|
490
|
+
attributes = {}
|
|
491
|
+
|
|
492
|
+
# Extract SI type (SI or PSI)
|
|
493
|
+
si_type = extract_value(parsed[:si_type])
|
|
494
|
+
|
|
495
|
+
# Extract publishers (should be "IEEE/ASTM")
|
|
496
|
+
if parsed[:publishers]
|
|
497
|
+
publishers_str = extract_value(parsed[:publishers])
|
|
498
|
+
# Split by slash to get individual publishers
|
|
499
|
+
pubs = publishers_str.split("/")
|
|
500
|
+
attributes[:publisher] = pubs.first
|
|
501
|
+
attributes[:copublisher] = pubs.drop(1) if pubs.length > 1
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
# Extract number
|
|
505
|
+
attributes[:code] = extract_value(parsed[:number])
|
|
506
|
+
|
|
507
|
+
# For PSI (draft), create proper Draft component object
|
|
508
|
+
if si_type == "PSI"
|
|
509
|
+
if parsed[:draft_version]
|
|
510
|
+
draft_version = extract_value(parsed[:draft_version])
|
|
511
|
+
# Create Draft component (Lutaml::Model object)
|
|
512
|
+
attributes[:draft_obj] =
|
|
513
|
+
Components::Draft.new(version: draft_version)
|
|
514
|
+
end
|
|
515
|
+
# Set PSI typed_stage (draft stage)
|
|
516
|
+
attributes[:typed_stage] = Identifiers::SiStandard::TYPED_STAGES.find do |ts|
|
|
517
|
+
ts.abbr.include?("PSI")
|
|
518
|
+
end
|
|
519
|
+
else
|
|
520
|
+
# Set SI typed_stage (published stage)
|
|
521
|
+
attributes[:typed_stage] = Identifiers::SiStandard::TYPED_STAGES.find do |ts|
|
|
522
|
+
ts.abbr.include?("SI")
|
|
523
|
+
end
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
# Extract year and month
|
|
527
|
+
attributes[:year] = extract_value(parsed[:year]) if parsed[:year]
|
|
528
|
+
attributes[:month] = extract_value(parsed[:month]) if parsed[:month]
|
|
529
|
+
|
|
530
|
+
# Handle relationships if present
|
|
531
|
+
if parsed[:relationship_type] || parsed[:relationship_clause]
|
|
532
|
+
attributes[:relationships] = build_relationships(parsed)
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
# Handle parenthetical content
|
|
536
|
+
handle_parameters(parsed, attributes)
|
|
537
|
+
|
|
538
|
+
# BOTH SI and PSI use SiStandard class - just different typed_stages
|
|
539
|
+
Identifiers::SiStandard.new(**attributes)
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
# Build multi-numbered identifier from parsed data
|
|
543
|
+
# @param parsed [Hash] parsed multi-numbered data
|
|
544
|
+
# @return [Identifiers::MultiNumberedIdentifier] multi-numbered identifier
|
|
545
|
+
def build_multi_numbered_identifier(parsed)
|
|
546
|
+
# Build primary identifier
|
|
547
|
+
primary_id = build_single_identifier(parsed[:primary_identifier],
|
|
548
|
+
building_secondary: false)
|
|
549
|
+
|
|
550
|
+
# Build secondary identifier based on format
|
|
551
|
+
if parsed[:secondary_crossref]
|
|
552
|
+
# Cross-reference format: /C62.22.1-1996
|
|
553
|
+
# Build directly to avoid re-parsing which could cause infinite recursion
|
|
554
|
+
crossref = parsed[:secondary_crossref]
|
|
555
|
+
# Pattern: slash >> "C" >> digits >> dot >> digits >> dot >> digits >> dash >> year_digits
|
|
556
|
+
# The parsed crossref is a string - extract the number part
|
|
557
|
+
# Format: C62.22.1-1996 where C is part of the crossref notation
|
|
558
|
+
secondary_id = Identifiers::Standard.new(
|
|
559
|
+
publisher: "IEEE",
|
|
560
|
+
number: extract_value(crossref),
|
|
561
|
+
)
|
|
562
|
+
elsif parsed[:secondary_joint]
|
|
563
|
+
# Joint standard format: ", Std 1177-1989"
|
|
564
|
+
# Build from parsed components
|
|
565
|
+
secondary_id = build_single_identifier(parsed[:secondary_joint],
|
|
566
|
+
building_secondary: true)
|
|
567
|
+
else
|
|
568
|
+
secondary_id = nil
|
|
569
|
+
end
|
|
570
|
+
|
|
571
|
+
Identifiers::MultiNumberedIdentifier.new(
|
|
572
|
+
primary_identifier: primary_id,
|
|
573
|
+
secondary_identifier: secondary_id,
|
|
574
|
+
)
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
# Determine which identifier class to use based on attributes
|
|
578
|
+
# CRITICAL: Use Scheme for type-based decisions, NOT hardcoded logic here
|
|
579
|
+
# Builder's job is ONLY to cast types, not make business decisions
|
|
580
|
+
def determine_identifier_class(attributes)
|
|
581
|
+
# Check for AIEE publisher FIRST (AIEE has its own identifier class)
|
|
582
|
+
# This must be checked before type-based routing because AIEE uses "No" as type
|
|
583
|
+
if attributes[:publisher] == "AIEE"
|
|
584
|
+
return Ieee::Aiee::Identifier
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
# Get type from attributes and use Scheme to locate class
|
|
588
|
+
type_code = attributes[:type]
|
|
589
|
+
|
|
590
|
+
# Use Scheme registry for type-to-class mapping
|
|
591
|
+
if type_code
|
|
592
|
+
klass = Ieee::Scheme.locate_identifier_klass_by_type_code(type_code)
|
|
593
|
+
return klass if klass
|
|
594
|
+
end
|
|
595
|
+
|
|
596
|
+
# Non-type-based routing (structural patterns, not business logic)
|
|
597
|
+
# These are structural checks, not type decisions
|
|
598
|
+
|
|
599
|
+
# Check for SI standards (handles both SI and PSI via typed_stage)
|
|
600
|
+
if ["SI", "PSI"].include?(type_code)
|
|
601
|
+
return Identifiers::SiStandard
|
|
602
|
+
end
|
|
603
|
+
|
|
604
|
+
# Check for interpretation supplements (structural: has interpretation flag or int_year)
|
|
605
|
+
if attributes[:interpretation] || attributes[:int_year]
|
|
606
|
+
return Identifiers::InterpretationIdentifier
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
# Check for conformance supplements (structural: has conf_number)
|
|
610
|
+
if attributes[:conf_number]
|
|
611
|
+
return Identifiers::ConformanceIdentifier
|
|
612
|
+
end
|
|
613
|
+
|
|
614
|
+
# Check for corrigendum supplements (structural: has cor_number)
|
|
615
|
+
if attributes[:cor_number]
|
|
616
|
+
return Identifiers::Corrigendum
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
# Check for multi-numbered standards (structural: has crossref or joint patterns)
|
|
620
|
+
# These are handled at the build() method level, not here
|
|
621
|
+
# (cross-reference patterns like /C62.22.1-1996 and joint standards)
|
|
622
|
+
|
|
623
|
+
# Check for adopted standards (parenthetical adoptions)
|
|
624
|
+
if attributes[:adoption] || (attributes[:parameters] && attributes[:parameters][:adoption])
|
|
625
|
+
return Identifiers::AdoptedStandard
|
|
626
|
+
end
|
|
627
|
+
|
|
628
|
+
# Check for redline standards (structural: has redline flag)
|
|
629
|
+
if attributes[:redline]
|
|
630
|
+
return Identifiers::RedlinedStandard
|
|
631
|
+
end
|
|
632
|
+
|
|
633
|
+
# Default to base identifier
|
|
634
|
+
Identifiers::Base
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
# Detect lead party for joint development identifiers
|
|
638
|
+
# @param attributes [Hash] the identifier attributes
|
|
639
|
+
# @return [String] the lead party ("IEEE", "ISO", or "IEC")
|
|
640
|
+
def detect_lead_party(attributes)
|
|
641
|
+
# Rule 1: Check for P prefix in code (IEEE-led)
|
|
642
|
+
if attributes[:code]&.start_with?("P") || attributes[:type] == "P"
|
|
643
|
+
return "IEEE"
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
# Rule 2: Check for IEEE draft notation in original input (IEEE-led)
|
|
647
|
+
if original_input&.match?(/\/D\d+/)
|
|
648
|
+
return "IEEE"
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
# Rule 3: Check for ISO stage codes (ISO-led)
|
|
652
|
+
iso_stages = %w[FDIS DIS CD WD PWI NP]
|
|
653
|
+
if attributes[:typed_stage]
|
|
654
|
+
stage_abbr = attributes[:typed_stage].abbr
|
|
655
|
+
stage_abbr = [stage_abbr] unless stage_abbr.is_a?(Array)
|
|
656
|
+
if stage_abbr.any? { |abbr| iso_stages.include?(abbr) }
|
|
657
|
+
return "ISO"
|
|
658
|
+
end
|
|
659
|
+
end
|
|
660
|
+
|
|
661
|
+
# Rule 4: Check for colon before year in original input (ISO-led)
|
|
662
|
+
if original_input&.match?(/:\d{4}/)
|
|
663
|
+
return "ISO"
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
# Rule 5: Default to first publisher
|
|
667
|
+
attributes[:publisher] || "IEEE"
|
|
668
|
+
end
|
|
669
|
+
|
|
670
|
+
# Merge an array of parsed hashes into a single hash
|
|
671
|
+
# @param parsed_array [Array<Hash>] array of parsed hashes
|
|
672
|
+
# @return [Hash] merged hash
|
|
673
|
+
def merge_parsed_array(parsed_array)
|
|
674
|
+
parsed_array.inject({}) do |result, hash|
|
|
675
|
+
result.merge(hash)
|
|
676
|
+
end
|
|
677
|
+
end
|
|
678
|
+
|
|
679
|
+
# Extract and normalize attributes from parsed data
|
|
680
|
+
# @param parsed [Hash] the parsed data
|
|
681
|
+
# @return [Hash] normalized attributes for Scheme
|
|
682
|
+
def extract_attributes(parsed)
|
|
683
|
+
attributes = {}
|
|
684
|
+
|
|
685
|
+
# Handle publishers
|
|
686
|
+
if parsed[:publishers]
|
|
687
|
+
pub_data = parsed[:publishers]
|
|
688
|
+
attributes[:publisher] = extract_value(pub_data[:publisher])
|
|
689
|
+
|
|
690
|
+
if pub_data[:copublishers]
|
|
691
|
+
copubs = pub_data[:copublishers]
|
|
692
|
+
copubs = [copubs] unless copubs.is_a?(Array)
|
|
693
|
+
attributes[:copublisher] = copubs.filter_map do |cp|
|
|
694
|
+
extract_value(cp[:copublisher])
|
|
695
|
+
end
|
|
696
|
+
end
|
|
697
|
+
elsif parsed[:publisher]
|
|
698
|
+
attributes[:publisher] = extract_value(parsed[:publisher])
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
# Build code component with parts and subparts
|
|
702
|
+
code_parts = []
|
|
703
|
+
code_parts << extract_value(parsed[:part]) if parsed[:part]
|
|
704
|
+
if parsed[:subpart]
|
|
705
|
+
subparts = parsed[:subpart]
|
|
706
|
+
subparts = [subparts] unless subparts.is_a?(Array)
|
|
707
|
+
code_parts.concat(subparts.filter_map { |sp| extract_value(sp) })
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
# Create code string with parts
|
|
711
|
+
code_str = extract_value(parsed[:number])
|
|
712
|
+
|
|
713
|
+
# Extract type and draft_status for typed_stage lookup
|
|
714
|
+
type_value = extract_value(parsed[:type])
|
|
715
|
+
draft_status_value = extract_value(parsed[:draft_status])
|
|
716
|
+
|
|
717
|
+
# Handle case where parser captured number without "P" prefix
|
|
718
|
+
# Check original input to see if there was a P before the number
|
|
719
|
+
# The ieee_p_identifier rule consumes P without capturing it
|
|
720
|
+
if !type_value && original_input&.match?(/IEEE\s+P/)
|
|
721
|
+
type_value = "P"
|
|
722
|
+
end
|
|
723
|
+
|
|
724
|
+
# Handle ANSI P prefix patterns (e.g., "ANSI PN42.34-2015")
|
|
725
|
+
if !type_value && original_input&.match?(/ANSI\s+P/)
|
|
726
|
+
# Extract P as type since it was in the original but parser stripped it
|
|
727
|
+
type_value = "P"
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
# NOTE: "P" is a project/draft stage indicator, NOT a code prefix
|
|
731
|
+
# It should be reflected in typed_stage, not in the Code component
|
|
732
|
+
# Do NOT prepend "P" to code_str - code.prefix should remain nil for project drafts
|
|
733
|
+
|
|
734
|
+
# Special case: For IEEE/CSA dual published patterns, strip P prefix from code
|
|
735
|
+
# Pattern: "IEEE/CSA P844.1-2017" -> code should be "844.1" not "P844.1"
|
|
736
|
+
if code_str&.start_with?("P") && original_input&.include?("/CSA")
|
|
737
|
+
# Check if the copublisher attribute indicates CSA
|
|
738
|
+
pub_data = parsed[:publishers]
|
|
739
|
+
has_csa_copub = if pub_data && pub_data[:copublishers]
|
|
740
|
+
copubs = pub_data[:copublishers]
|
|
741
|
+
copubs = [copubs] unless copubs.is_a?(Array)
|
|
742
|
+
copubs.any? do |cp|
|
|
743
|
+
extract_value(cp[:copublisher])&.include?("CSA")
|
|
744
|
+
end
|
|
745
|
+
else
|
|
746
|
+
original_input&.include?("/CSA")
|
|
747
|
+
end
|
|
748
|
+
|
|
749
|
+
if has_csa_copub
|
|
750
|
+
code_str = code_str.sub(/^P/, "")
|
|
751
|
+
end
|
|
752
|
+
end
|
|
753
|
+
|
|
754
|
+
if code_str && !code_parts.empty?
|
|
755
|
+
code_str += ".#{code_parts.join('.')}"
|
|
756
|
+
end
|
|
757
|
+
|
|
758
|
+
# Year detection: If code_str ends with year-like pattern (dash + 4 digits, 1884-2099)
|
|
759
|
+
# and there's no year attribute yet, treat it as a year
|
|
760
|
+
# Examples: "535-2013", "802.1AC-2016", "C37.41-2016"
|
|
761
|
+
# AIEE established in 1884, so years range from 1884 to 2099
|
|
762
|
+
# ONLY apply this when there are NO code_parts (meaning parser didn't capture parts separately)
|
|
763
|
+
# This prevents breaking legitimate dual-published identifiers
|
|
764
|
+
# Match ending with dash followed by 4 digits only (not dot, to preserve 802.1AC patterns)
|
|
765
|
+
if code_str && !parsed[:year] && code_parts.empty? && (match = code_str.match(/^(.+)-(\d{4})$/))
|
|
766
|
+
potential_year = match[2].to_i
|
|
767
|
+
if potential_year.between?(1884, 2099)
|
|
768
|
+
# This is a year - extract it
|
|
769
|
+
code_str = match[1] # Remove year from code
|
|
770
|
+
parsed[:year] = match[2] # Add to parsed for extraction below
|
|
771
|
+
end
|
|
772
|
+
end
|
|
773
|
+
|
|
774
|
+
attributes[:code] = code_str
|
|
775
|
+
|
|
776
|
+
# Extract year - check for edition_month parsed separately
|
|
777
|
+
if parsed[:year]
|
|
778
|
+
year_str = extract_value(parsed[:year])
|
|
779
|
+
attributes[:year] = year_str
|
|
780
|
+
end
|
|
781
|
+
|
|
782
|
+
# Extract edition_month if parsed separately
|
|
783
|
+
if parsed[:edition_month]
|
|
784
|
+
attributes[:edition_month] = extract_value(parsed[:edition_month])
|
|
785
|
+
end
|
|
786
|
+
|
|
787
|
+
# Set type attribute for backward compatibility (after P extraction)
|
|
788
|
+
# NOTE: "P" IS a type code that maps to ProjectDraftIdentifier via Scheme
|
|
789
|
+
# Type can be: "Std", "No", "P" (project draft), etc.
|
|
790
|
+
attributes[:type] = type_value if type_value
|
|
791
|
+
|
|
792
|
+
# Lookup typed_stage from registry
|
|
793
|
+
typed_stage_abbr = determine_stage_abbr(type_value, draft_status_value,
|
|
794
|
+
parsed)
|
|
795
|
+
if typed_stage_abbr
|
|
796
|
+
attributes[:typed_stage] =
|
|
797
|
+
Ieee::Scheme.locate_typed_stage_by_abbr(typed_stage_abbr)
|
|
798
|
+
end
|
|
799
|
+
|
|
800
|
+
attributes[:draft_status] = draft_status_value
|
|
801
|
+
|
|
802
|
+
# Optional attributes (excluding part/subpart since they're in code)
|
|
803
|
+
extract_optional(parsed, attributes, :edition)
|
|
804
|
+
extract_optional(parsed, attributes, :revision)
|
|
805
|
+
|
|
806
|
+
# Month/day - always extract if present (but not if already extracted from year)
|
|
807
|
+
unless attributes[:edition_month]
|
|
808
|
+
extract_optional(parsed, attributes,
|
|
809
|
+
:month)
|
|
810
|
+
end
|
|
811
|
+
extract_optional(parsed, attributes, :day)
|
|
812
|
+
|
|
813
|
+
# Handle draft (can be complex)
|
|
814
|
+
handle_draft(parsed, attributes)
|
|
815
|
+
|
|
816
|
+
# Handle corrigendum
|
|
817
|
+
handle_corrigendum(parsed, attributes)
|
|
818
|
+
|
|
819
|
+
# Handle amendment
|
|
820
|
+
handle_amendment(parsed, attributes)
|
|
821
|
+
|
|
822
|
+
# Handle interpretation (already extracted as boolean)
|
|
823
|
+
# attributes[:interpretation] = true if parsed[:interpretation]
|
|
824
|
+
|
|
825
|
+
# Handle conformance
|
|
826
|
+
handle_conformance(parsed, attributes)
|
|
827
|
+
|
|
828
|
+
# Handle ASHRAE copub
|
|
829
|
+
handle_ashrae_copub(parsed, attributes)
|
|
830
|
+
|
|
831
|
+
# Handle IEEE crossref
|
|
832
|
+
handle_ieee_crossref(parsed, attributes)
|
|
833
|
+
|
|
834
|
+
# Handle reaffirmed
|
|
835
|
+
handle_reaffirmed(parsed, attributes)
|
|
836
|
+
|
|
837
|
+
# Handle additional parameters
|
|
838
|
+
handle_parameters(parsed, attributes)
|
|
839
|
+
|
|
840
|
+
# Book nickname
|
|
841
|
+
if parsed[:nickname]
|
|
842
|
+
attributes[:nickname] = extract_value(parsed[:nickname])
|
|
843
|
+
end
|
|
844
|
+
|
|
845
|
+
# Interpretation
|
|
846
|
+
attributes[:interpretation] = true if parsed[:interpretation]
|
|
847
|
+
|
|
848
|
+
# Redline
|
|
849
|
+
attributes[:redline] = true if parsed[:redline]
|
|
850
|
+
|
|
851
|
+
attributes
|
|
852
|
+
end
|
|
853
|
+
|
|
854
|
+
# Determine stage abbreviation for TYPED_STAGE lookup
|
|
855
|
+
# @param type_value [String] the type value (e.g., "Std", "P")
|
|
856
|
+
# @param draft_status_value [String] the draft status (e.g., "Unapproved")
|
|
857
|
+
# @param parsed [Hash] the full parsed data
|
|
858
|
+
# @return [String, nil] the abbreviation to use for stage lookup
|
|
859
|
+
def determine_stage_abbr(type_value, _draft_status_value, parsed)
|
|
860
|
+
# Check for specific draft notation (D1, D2, etc.)
|
|
861
|
+
if parsed[:draft]
|
|
862
|
+
draft_data = parsed[:draft]
|
|
863
|
+
if draft_data.is_a?(Array)
|
|
864
|
+
draft_data = draft_data.inject({}) do |r, e|
|
|
865
|
+
r.merge(e)
|
|
866
|
+
end
|
|
867
|
+
end
|
|
868
|
+
|
|
869
|
+
if draft_data.is_a?(Hash) && draft_data[:draft_version]
|
|
870
|
+
dv = draft_data[:draft_version]
|
|
871
|
+
version = if dv.is_a?(Array)
|
|
872
|
+
dv.map do |v|
|
|
873
|
+
extract_value(v)
|
|
874
|
+
end.join
|
|
875
|
+
else
|
|
876
|
+
extract_value(dv)
|
|
877
|
+
end
|
|
878
|
+
|
|
879
|
+
# Construct draft notation like "D1", "D2", etc.
|
|
880
|
+
if version
|
|
881
|
+
draft_abbr = "D#{version}"
|
|
882
|
+
# Check if this specific draft stage is in registry
|
|
883
|
+
stage = Ieee::Scheme.locate_typed_stage_by_abbr(draft_abbr)
|
|
884
|
+
return draft_abbr if stage&.abbr&.include?(draft_abbr)
|
|
885
|
+
end
|
|
886
|
+
end
|
|
887
|
+
end
|
|
888
|
+
|
|
889
|
+
# Check type value for known abbreviations
|
|
890
|
+
if type_value
|
|
891
|
+
# Remove leading "P" and check if it exists in registry
|
|
892
|
+
if type_value.start_with?("P")
|
|
893
|
+
# Could be just "P" prefix or "P" as type indicator
|
|
894
|
+
# If the type is literally "P" followed by numbers, it's a project identifier
|
|
895
|
+
# Return "P" to get the generic project typed_stage
|
|
896
|
+
return "P"
|
|
897
|
+
elsif type_value == "Std"
|
|
898
|
+
return "Std"
|
|
899
|
+
elsif type_value.match?(/^No\.?$/)
|
|
900
|
+
return type_value
|
|
901
|
+
end
|
|
902
|
+
end
|
|
903
|
+
|
|
904
|
+
# Default to "Std" for published standards
|
|
905
|
+
"Std"
|
|
906
|
+
end
|
|
907
|
+
|
|
908
|
+
# Extract a simple value from parsed data
|
|
909
|
+
# @param value [Object] the value to extract
|
|
910
|
+
# @return [String, nil] the extracted string value
|
|
911
|
+
def extract_value(value)
|
|
912
|
+
return nil if value.nil?
|
|
913
|
+
return nil if value.is_a?(Array) && value.empty?
|
|
914
|
+
|
|
915
|
+
if value.is_a?(Array)
|
|
916
|
+
joined = value.join
|
|
917
|
+
return joined.length.positive? ? joined : nil
|
|
918
|
+
end
|
|
919
|
+
|
|
920
|
+
str_value = value.to_s.strip
|
|
921
|
+
str_value.length.positive? ? str_value : nil
|
|
922
|
+
end
|
|
923
|
+
|
|
924
|
+
# Extract optional attribute if present
|
|
925
|
+
def extract_optional(parsed, attributes, key)
|
|
926
|
+
value = extract_value(parsed[key])
|
|
927
|
+
attributes[key] = value if value
|
|
928
|
+
end
|
|
929
|
+
|
|
930
|
+
# Handle draft information
|
|
931
|
+
def handle_draft(parsed, attributes)
|
|
932
|
+
draft_data = parsed[:draft] || parsed[:digit_draft]
|
|
933
|
+
return unless draft_data
|
|
934
|
+
|
|
935
|
+
# Draft can be an array of hash elements or a single hash
|
|
936
|
+
if draft_data.is_a?(Array)
|
|
937
|
+
# Merge all elements in the array
|
|
938
|
+
merged = draft_data.inject({}) { |result, elem| result.merge(elem) }
|
|
939
|
+
draft_data = merged
|
|
940
|
+
end
|
|
941
|
+
|
|
942
|
+
# Extract draft version and revision
|
|
943
|
+
version = nil
|
|
944
|
+
revision = nil
|
|
945
|
+
month = nil
|
|
946
|
+
year = nil
|
|
947
|
+
day = nil
|
|
948
|
+
comma_before_month = false
|
|
949
|
+
|
|
950
|
+
if draft_data.is_a?(Hash)
|
|
951
|
+
if draft_data[:draft_version]
|
|
952
|
+
dv = draft_data[:draft_version]
|
|
953
|
+
version = if dv.is_a?(Array)
|
|
954
|
+
dv.map { |v| extract_value(v) }.join
|
|
955
|
+
else
|
|
956
|
+
extract_value(dv)
|
|
957
|
+
end
|
|
958
|
+
end
|
|
959
|
+
|
|
960
|
+
revision = extract_value(draft_data[:revision]) if draft_data[:revision]
|
|
961
|
+
|
|
962
|
+
# Extract date information from draft data
|
|
963
|
+
month_slice = draft_data[:month]
|
|
964
|
+
month = extract_value(month_slice) if month_slice
|
|
965
|
+
year = extract_value(draft_data[:year]) if draft_data[:year]
|
|
966
|
+
day = extract_value(draft_data[:day]) if draft_data[:day]
|
|
967
|
+
|
|
968
|
+
# Detect comma before month and space before draft by checking the original input
|
|
969
|
+
if original_input
|
|
970
|
+
if month
|
|
971
|
+
# Look for ", Month" pattern in the original input
|
|
972
|
+
comma_before_month = original_input.match?(/,\s+#{Regexp.escape(month)}/i)
|
|
973
|
+
end
|
|
974
|
+
|
|
975
|
+
# Check if there's a space before /D in the original input
|
|
976
|
+
if version && original_input.match?(/\s+\/D#{Regexp.escape(version)}/i)
|
|
977
|
+
attributes[:space_before_draft] = true
|
|
978
|
+
end
|
|
979
|
+
end
|
|
980
|
+
else
|
|
981
|
+
version = extract_value(draft_data)
|
|
982
|
+
end
|
|
983
|
+
|
|
984
|
+
# Create Draft component object if we have version info
|
|
985
|
+
if version
|
|
986
|
+
draft_obj = Components::Draft.new(
|
|
987
|
+
version: version,
|
|
988
|
+
revision: revision,
|
|
989
|
+
month: month,
|
|
990
|
+
year: year,
|
|
991
|
+
day: day,
|
|
992
|
+
)
|
|
993
|
+
draft_obj.comma_before_month = comma_before_month
|
|
994
|
+
attributes[:draft_obj] = draft_obj
|
|
995
|
+
attributes[:draft] = draft_obj.to_s
|
|
996
|
+
end
|
|
997
|
+
end
|
|
998
|
+
|
|
999
|
+
# Handle corrigendum information
|
|
1000
|
+
def handle_corrigendum(parsed, attributes)
|
|
1001
|
+
if parsed[:corrigendum].is_a?(Hash)
|
|
1002
|
+
cor_data = parsed[:corrigendum]
|
|
1003
|
+
attributes[:cor_number] = extract_value(cor_data[:cor_number])
|
|
1004
|
+
if cor_data[:cor_year]
|
|
1005
|
+
attributes[:cor_year] =
|
|
1006
|
+
extract_value(cor_data[:cor_year])
|
|
1007
|
+
end
|
|
1008
|
+
elsif parsed[:corrigendum]
|
|
1009
|
+
attributes[:corrigendum] = extract_value(parsed[:corrigendum])
|
|
1010
|
+
end
|
|
1011
|
+
end
|
|
1012
|
+
|
|
1013
|
+
# Handle amendment information
|
|
1014
|
+
def handle_amendment(parsed, attributes)
|
|
1015
|
+
if parsed[:amendment].is_a?(Hash)
|
|
1016
|
+
amd_data = parsed[:amendment]
|
|
1017
|
+
attributes[:amd_number] = extract_value(amd_data[:amd_number])
|
|
1018
|
+
if amd_data[:amd_year]
|
|
1019
|
+
attributes[:amd_year] =
|
|
1020
|
+
extract_value(amd_data[:amd_year])
|
|
1021
|
+
end
|
|
1022
|
+
elsif parsed[:amendment]
|
|
1023
|
+
attributes[:amendment] = extract_value(parsed[:amendment])
|
|
1024
|
+
end
|
|
1025
|
+
end
|
|
1026
|
+
|
|
1027
|
+
# Handle reaffirmed information
|
|
1028
|
+
def handle_reaffirmed(parsed, attributes)
|
|
1029
|
+
if parsed[:reaffirmed].is_a?(Hash)
|
|
1030
|
+
reaf_data = parsed[:reaffirmed]
|
|
1031
|
+
attributes[:reaffirmed] = extract_value(reaf_data[:year])
|
|
1032
|
+
elsif parsed[:reaffirmed]
|
|
1033
|
+
attributes[:reaffirmed] = extract_value(parsed[:reaffirmed])
|
|
1034
|
+
end
|
|
1035
|
+
end
|
|
1036
|
+
|
|
1037
|
+
# Handle conformance document information
|
|
1038
|
+
def handle_conformance(parsed, attributes)
|
|
1039
|
+
if parsed[:conformance].is_a?(Hash)
|
|
1040
|
+
conf_data = parsed[:conformance]
|
|
1041
|
+
attributes[:conf_number] = extract_value(conf_data[:conf_number])
|
|
1042
|
+
if conf_data[:conf_year]
|
|
1043
|
+
attributes[:conf_year] = extract_value(conf_data[:conf_year])
|
|
1044
|
+
end
|
|
1045
|
+
elsif parsed[:conformance]
|
|
1046
|
+
attributes[:conformance] = extract_value(parsed[:conformance])
|
|
1047
|
+
end
|
|
1048
|
+
end
|
|
1049
|
+
|
|
1050
|
+
# Handle ASHRAE joint publication information
|
|
1051
|
+
def handle_ashrae_copub(parsed, attributes)
|
|
1052
|
+
if parsed[:ashrae_copub].is_a?(Hash)
|
|
1053
|
+
ashrae_data = parsed[:ashrae_copub]
|
|
1054
|
+
attributes[:ashrae_number] =
|
|
1055
|
+
extract_value(ashrae_data[:ashrae_number])
|
|
1056
|
+
if ashrae_data[:ashrae_year]
|
|
1057
|
+
attributes[:ashrae_year] = extract_value(ashrae_data[:ashrae_year])
|
|
1058
|
+
end
|
|
1059
|
+
elsif parsed[:ashrae_copub]
|
|
1060
|
+
attributes[:ashrae_copub] = extract_value(parsed[:ashrae_copub])
|
|
1061
|
+
end
|
|
1062
|
+
end
|
|
1063
|
+
|
|
1064
|
+
# Handle IEEE cross-reference information
|
|
1065
|
+
def handle_ieee_crossref(parsed, attributes)
|
|
1066
|
+
if parsed[:ieee_crossref].is_a?(Hash)
|
|
1067
|
+
parsed[:ieee_crossref]
|
|
1068
|
+
# Extract the cross-reference string (e.g., "C62.22.1-1996")
|
|
1069
|
+
# Store it for rendering
|
|
1070
|
+
attributes[:crossref] =
|
|
1071
|
+
"/C#{extract_value(crossref).to_s.sub(/^\//, '')}"
|
|
1072
|
+
elsif parsed[:ieee_crossref]
|
|
1073
|
+
attributes[:crossref] = extract_value(parsed[:ieee_crossref])
|
|
1074
|
+
end
|
|
1075
|
+
end
|
|
1076
|
+
|
|
1077
|
+
# Handle additional parameters
|
|
1078
|
+
def handle_parameters(parsed, attributes)
|
|
1079
|
+
if parsed[:parameters].is_a?(Hash)
|
|
1080
|
+
param_data = parsed[:parameters]
|
|
1081
|
+
|
|
1082
|
+
# Handle parenthetical content (for multi-part adoptions like "ANSI Y32.21-1976, NCTA 006-0975")
|
|
1083
|
+
if param_data[:parenthetical_content]
|
|
1084
|
+
attributes[:parenthetical_content] =
|
|
1085
|
+
extract_value(param_data[:parenthetical_content])
|
|
1086
|
+
end
|
|
1087
|
+
|
|
1088
|
+
if param_data[:revision_of]
|
|
1089
|
+
attributes[:revision_of] =
|
|
1090
|
+
extract_value(param_data[:revision_of])
|
|
1091
|
+
end
|
|
1092
|
+
if param_data[:amendment_to]
|
|
1093
|
+
attributes[:amendment_to] =
|
|
1094
|
+
extract_value(param_data[:amendment_to])
|
|
1095
|
+
end
|
|
1096
|
+
if param_data[:adoption]
|
|
1097
|
+
attributes[:adoption] =
|
|
1098
|
+
extract_value(param_data[:adoption])
|
|
1099
|
+
end
|
|
1100
|
+
if param_data[:note]
|
|
1101
|
+
attributes[:note] =
|
|
1102
|
+
extract_value(param_data[:note])
|
|
1103
|
+
end
|
|
1104
|
+
end
|
|
1105
|
+
end
|
|
1106
|
+
|
|
1107
|
+
# Build relationships from parsed relationship clause (Pattern 4)
|
|
1108
|
+
# @param parsed_hash [Hash] the parsed data containing relationship information
|
|
1109
|
+
# @return [Array<Components::Relationship>] array of Relationship objects
|
|
1110
|
+
def build_relationships(parsed_hash)
|
|
1111
|
+
return [] unless parsed_hash[:relationship_type] || parsed_hash[:relationship_clause]
|
|
1112
|
+
|
|
1113
|
+
relationships = []
|
|
1114
|
+
|
|
1115
|
+
# Main relationship
|
|
1116
|
+
if parsed_hash[:relationship_type]
|
|
1117
|
+
rel_type = extract_relationship_type(parsed_hash[:relationship_type])
|
|
1118
|
+
related = parse_identifier_list(parsed_hash[:related_ids])
|
|
1119
|
+
|
|
1120
|
+
# Handle "as amended by" clause
|
|
1121
|
+
amendments = nil
|
|
1122
|
+
approved_flag = false
|
|
1123
|
+
|
|
1124
|
+
if parsed_hash[:amendments]
|
|
1125
|
+
# Check if it's the "and its approved amendments" flag
|
|
1126
|
+
if parsed_hash[:amendments].is_a?(Hash) && parsed_hash[:amendments][:approved_amendments]
|
|
1127
|
+
approved_flag = true
|
|
1128
|
+
else
|
|
1129
|
+
amendments = parse_identifier_list(parsed_hash[:amendments])
|
|
1130
|
+
end
|
|
1131
|
+
end
|
|
1132
|
+
|
|
1133
|
+
relationships << Components::Relationship.new(
|
|
1134
|
+
relationship_type: rel_type,
|
|
1135
|
+
related_identifiers: related,
|
|
1136
|
+
intermediate_amendments: amendments,
|
|
1137
|
+
approved_amendments_flag: approved_flag,
|
|
1138
|
+
)
|
|
1139
|
+
end
|
|
1140
|
+
|
|
1141
|
+
# Additional relationships (separated by " / ")
|
|
1142
|
+
if parsed_hash[:additional_rels]
|
|
1143
|
+
additional = parsed_hash[:additional_rels]
|
|
1144
|
+
additional = [additional] unless additional.is_a?(Array)
|
|
1145
|
+
|
|
1146
|
+
additional.each do |rel_data|
|
|
1147
|
+
rel_type = extract_relationship_type(rel_data[:relationship_type])
|
|
1148
|
+
related = parse_identifier_list(rel_data[:related_ids])
|
|
1149
|
+
|
|
1150
|
+
# Handle "as amended by" clause for additional relationships
|
|
1151
|
+
amendments = nil
|
|
1152
|
+
approved_flag = false
|
|
1153
|
+
|
|
1154
|
+
if rel_data[:amendments]
|
|
1155
|
+
if rel_data[:amendments].is_a?(Hash) && rel_data[:amendments][:approved_amendments]
|
|
1156
|
+
approved_flag = true
|
|
1157
|
+
else
|
|
1158
|
+
amendments = parse_identifier_list(rel_data[:amendments])
|
|
1159
|
+
end
|
|
1160
|
+
end
|
|
1161
|
+
|
|
1162
|
+
relationships << Components::Relationship.new(
|
|
1163
|
+
relationship_type: rel_type,
|
|
1164
|
+
related_identifiers: related,
|
|
1165
|
+
intermediate_amendments: amendments,
|
|
1166
|
+
approved_amendments_flag: approved_flag,
|
|
1167
|
+
)
|
|
1168
|
+
end
|
|
1169
|
+
end
|
|
1170
|
+
|
|
1171
|
+
relationships
|
|
1172
|
+
end
|
|
1173
|
+
|
|
1174
|
+
# Extract relationship type from parsed hash
|
|
1175
|
+
# @param type_hash [Hash] hash with relationship type key
|
|
1176
|
+
# @return [String] the relationship type constant name
|
|
1177
|
+
def extract_relationship_type(type_hash)
|
|
1178
|
+
return nil unless type_hash.is_a?(Hash)
|
|
1179
|
+
|
|
1180
|
+
# type_hash has key like :revision_of, :amendment_to, etc.
|
|
1181
|
+
type_hash.keys.first.to_s
|
|
1182
|
+
end
|
|
1183
|
+
|
|
1184
|
+
# Parse a list of identifier strings into identifier objects
|
|
1185
|
+
# @param list_data [Hash, Array, nil] the parsed identifier list data
|
|
1186
|
+
# @return [Array<Identifiers::Base>] array of parsed identifier objects
|
|
1187
|
+
def parse_identifier_list(list_data)
|
|
1188
|
+
return [] unless list_data
|
|
1189
|
+
|
|
1190
|
+
# Extract identifier strings from parsed data
|
|
1191
|
+
id_strings = extract_identifier_strings(list_data)
|
|
1192
|
+
|
|
1193
|
+
# Recursively parse each identifier string
|
|
1194
|
+
id_strings.map do |id_str|
|
|
1195
|
+
# Use Identifiers::Base.parse for recursive parsing
|
|
1196
|
+
Identifiers::Base.parse(id_str)
|
|
1197
|
+
rescue Parslet::ParseFailed
|
|
1198
|
+
# If parsing fails, create minimal identifier with just the string
|
|
1199
|
+
# This maintains graceful degradation
|
|
1200
|
+
Identifiers::Base.new(parenthetical_content: id_str)
|
|
1201
|
+
end
|
|
1202
|
+
end
|
|
1203
|
+
|
|
1204
|
+
# Extract identifier strings from parsed list data
|
|
1205
|
+
# @param list_data [Hash, Array] the parsed list data
|
|
1206
|
+
# @return [Array<String>] array of identifier strings
|
|
1207
|
+
def extract_identifier_strings(list_data)
|
|
1208
|
+
if list_data.is_a?(Array)
|
|
1209
|
+
# Array of id hashes: [{id: "..."}, {id: "..."}]
|
|
1210
|
+
list_data.map { |item| item[:id].to_s.strip }
|
|
1211
|
+
elsif list_data.is_a?(Hash) && list_data[:id]
|
|
1212
|
+
# Single id hash: {id: "..."}
|
|
1213
|
+
[list_data[:id].to_s.strip]
|
|
1214
|
+
else
|
|
1215
|
+
[]
|
|
1216
|
+
end
|
|
1217
|
+
end
|
|
1218
|
+
|
|
1219
|
+
# Build combined AIEE identifier from "and"-separated identifiers
|
|
1220
|
+
# @param parsed [Hash] parsed combined AIEE data
|
|
1221
|
+
# @return [Identifiers::CombinedAiee] combined AIEE identifier
|
|
1222
|
+
def build_combined_aiee(parsed)
|
|
1223
|
+
# Build each AIEE identifier using AIEE builder
|
|
1224
|
+
aiee_builder = Aiee::Builder.new
|
|
1225
|
+
first_id = aiee_builder.build(parsed[:first_aiee])
|
|
1226
|
+
second_id = aiee_builder.build(parsed[:second_aiee])
|
|
1227
|
+
|
|
1228
|
+
# Create a simple combined identifier (reuse DualPublished pattern)
|
|
1229
|
+
Identifiers::DualPublished.new(
|
|
1230
|
+
first_identifier: first_id,
|
|
1231
|
+
second_identifier: second_id,
|
|
1232
|
+
separator: " and ",
|
|
1233
|
+
)
|
|
1234
|
+
end
|
|
1235
|
+
end
|
|
1236
|
+
end
|
|
1237
|
+
end
|