newsmlg2 0.1.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 +7 -0
- data/.github/workflows/docs.yml +63 -0
- data/.github/workflows/links.yml +99 -0
- data/.github/workflows/performance.yml +25 -0
- data/.github/workflows/rake.yml +19 -0
- data/.github/workflows/release.yml +34 -0
- data/.gitignore +17 -0
- data/.rubocop.yml +51 -0
- data/CHANGELOG.md +31 -0
- data/CLAUDE.md +77 -0
- data/Gemfile +15 -0
- data/LICENSE +24 -0
- data/README.adoc +135 -0
- data/Rakefile +15 -0
- data/docs/Gemfile +6 -0
- data/docs/_config.yml +4 -0
- data/docs/index.md +15 -0
- data/docs/lychee.toml +4 -0
- data/docs/usage.md +36 -0
- data/lib/newsmlg2/base/administrative_metadata_group.rb +40 -0
- data/lib/newsmlg2/base/arbitrary_value_attributes.rb +13 -0
- data/lib/newsmlg2/base/authority_attributes.rb +14 -0
- data/lib/newsmlg2/base/common_power_attributes.rb +17 -0
- data/lib/newsmlg2/base/concept_definition_group.rb +25 -0
- data/lib/newsmlg2/base/concept_relationships_group.rb +22 -0
- data/lib/newsmlg2/base/confirmation_status_attributes.rb +13 -0
- data/lib/newsmlg2/base/deprecated_link_attributes.rb +14 -0
- data/lib/newsmlg2/base/descriptive_metadata_group.rb +54 -0
- data/lib/newsmlg2/base/entity_details_group.rb +28 -0
- data/lib/newsmlg2/base/flex_attributes.rb +13 -0
- data/lib/newsmlg2/base/i18n_attributes.rb +14 -0
- data/lib/newsmlg2/base/item_management_group.rb +59 -0
- data/lib/newsmlg2/base/media_content_characteristics1.rb +22 -0
- data/lib/newsmlg2/base/news_content_attributes.rb +18 -0
- data/lib/newsmlg2/base/news_content_characteristics.rb +30 -0
- data/lib/newsmlg2/base/news_content_type_attributes.rb +17 -0
- data/lib/newsmlg2/base/persistent_edit_attributes.rb +13 -0
- data/lib/newsmlg2/base/qualifying_attributes.rb +13 -0
- data/lib/newsmlg2/base/quantify_attributes.rb +13 -0
- data/lib/newsmlg2/base/ranking_attributes.rb +13 -0
- data/lib/newsmlg2/base/recurrence_rule_attributes.rb +18 -0
- data/lib/newsmlg2/base/target_resource_attributes.rb +20 -0
- data/lib/newsmlg2/base/time_validity_attributes.rb +13 -0
- data/lib/newsmlg2/base.rb +35 -0
- data/lib/newsmlg2/builder/node.rb +125 -0
- data/lib/newsmlg2/builder.rb +69 -0
- data/lib/newsmlg2/catalog.rb +38 -0
- data/lib/newsmlg2/catalog_cache.rb +49 -0
- data/lib/newsmlg2/catalog_ref.rb +13 -0
- data/lib/newsmlg2/catalog_store.rb +66 -0
- data/lib/newsmlg2/catalogs/catalog.IPTC-G2-Standards_32.xml +620 -0
- data/lib/newsmlg2/catalogs/catalog.IPTC-G2-Standards_33.xml +625 -0
- data/lib/newsmlg2/catalogs/catalog.IPTC-G2-Standards_34.xml +626 -0
- data/lib/newsmlg2/catalogs/catalog.IPTC-G2-Standards_35.xml +635 -0
- data/lib/newsmlg2/catalogs/catalog.IPTC-G2-Standards_36.xml +644 -0
- data/lib/newsmlg2/catalogs/catalog.IPTC-G2-Standards_37.xml +661 -0
- data/lib/newsmlg2/catalogs/catalog.IPTC-G2-Standards_38.xml +674 -0
- data/lib/newsmlg2/catalogs/catalog.IPTC-G2-Standards_39.xml +682 -0
- data/lib/newsmlg2/catalogs/catalog.IPTC-G2-Standards_40.xml +724 -0
- data/lib/newsmlg2/catalogs/catalog.IPTC-G2-Standards_41.xml +729 -0
- data/lib/newsmlg2/configuration.rb +61 -0
- data/lib/newsmlg2/document.rb +123 -0
- data/lib/newsmlg2/errors.rb +18 -0
- data/lib/newsmlg2/i18n.rb +20 -0
- data/lib/newsmlg2/items/any_item.rb +180 -0
- data/lib/newsmlg2/items/catalog_item.rb +24 -0
- data/lib/newsmlg2/items/concept_item.rb +23 -0
- data/lib/newsmlg2/items/content_meta.rb +73 -0
- data/lib/newsmlg2/items/item_ref.rb +13 -0
- data/lib/newsmlg2/items/knowledge_item.rb +68 -0
- data/lib/newsmlg2/items/news_item.rb +130 -0
- data/lib/newsmlg2/items/news_message.rb +142 -0
- data/lib/newsmlg2/items/package_item.rb +82 -0
- data/lib/newsmlg2/items/part_meta.rb +68 -0
- data/lib/newsmlg2/items/planning_item.rb +160 -0
- data/lib/newsmlg2/nar_model.rb +76 -0
- data/lib/newsmlg2/nar_namespace.rb +10 -0
- data/lib/newsmlg2/nitf_namespace.rb +9 -0
- data/lib/newsmlg2/same_as_scheme.rb +15 -0
- data/lib/newsmlg2/scheme.rb +30 -0
- data/lib/newsmlg2/types/approximate_date_time_prop_type.rb +14 -0
- data/lib/newsmlg2/types/bag.rb +16 -0
- data/lib/newsmlg2/types/block_types.rb +62 -0
- data/lib/newsmlg2/types/concept.rb +36 -0
- data/lib/newsmlg2/types/concept_id.rb +17 -0
- data/lib/newsmlg2/types/concept_name_type.rb +17 -0
- data/lib/newsmlg2/types/content_meta_types.rb +152 -0
- data/lib/newsmlg2/types/date_opt_time_prop_type.rb +12 -0
- data/lib/newsmlg2/types/date_time_or_null_prop_type.rb +12 -0
- data/lib/newsmlg2/types/date_time_prop_type.rb +12 -0
- data/lib/newsmlg2/types/event_details.rb +213 -0
- data/lib/newsmlg2/types/ext_property.rb +21 -0
- data/lib/newsmlg2/types/facet.rb +17 -0
- data/lib/newsmlg2/types/flex1_prop_type.rb +32 -0
- data/lib/newsmlg2/types/flex_location_prop_type.rb +43 -0
- data/lib/newsmlg2/types/flex_party_prop_type.rb +49 -0
- data/lib/newsmlg2/types/flex_prop2_type.rb +26 -0
- data/lib/newsmlg2/types/flex_prop_type.rb +17 -0
- data/lib/newsmlg2/types/geo.rb +92 -0
- data/lib/newsmlg2/types/hierarchy_info.rb +17 -0
- data/lib/newsmlg2/types/ids.rb +28 -0
- data/lib/newsmlg2/types/inline_types.rb +56 -0
- data/lib/newsmlg2/types/intl_string_type.rb +17 -0
- data/lib/newsmlg2/types/intl_string_type2.rb +14 -0
- data/lib/newsmlg2/types/item_management.rb +74 -0
- data/lib/newsmlg2/types/link.rb +40 -0
- data/lib/newsmlg2/types/object_details.rb +40 -0
- data/lib/newsmlg2/types/party_details.rb +258 -0
- data/lib/newsmlg2/types/poi.rb +79 -0
- data/lib/newsmlg2/types/qcode_prop_type.rb +12 -0
- data/lib/newsmlg2/types/qual_prop_type.rb +23 -0
- data/lib/newsmlg2/types/qual_rel_prop_type.rb +18 -0
- data/lib/newsmlg2/types/related_concept.rb +71 -0
- data/lib/newsmlg2/types/rights.rb +84 -0
- data/lib/newsmlg2/types/ruby_annotation.rb +55 -0
- data/lib/newsmlg2/types/same_as.rb +17 -0
- data/lib/newsmlg2/types/truncated_date_time_prop_type.rb +13 -0
- data/lib/newsmlg2/types/versioned_string_type.rb +10 -0
- data/lib/newsmlg2/types/xml_base.rb +12 -0
- data/lib/newsmlg2/types/xml_lang.rb +12 -0
- data/lib/newsmlg2/types.rb +166 -0
- data/lib/newsmlg2/utils.rb +42 -0
- data/lib/newsmlg2/version.rb +5 -0
- data/lib/newsmlg2.rb +181 -0
- data/lib/tasks/performance.rake +72 -0
- data/newsmlg2.gemspec +34 -0
- metadata +185 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Newsmlg2
|
|
4
|
+
# Shared value types (XSD complex types usable as element payloads) and
|
|
5
|
+
# W3C xml-namespace attribute types.
|
|
6
|
+
module Types
|
|
7
|
+
autoload :A, 'newsmlg2/types/inline_types'
|
|
8
|
+
autoload :Affiliation, 'newsmlg2/types/party_details'
|
|
9
|
+
autoload :Access, 'newsmlg2/types/poi'
|
|
10
|
+
autoload :AccessStatus, 'newsmlg2/types/event_details'
|
|
11
|
+
autoload :Address, 'newsmlg2/types/party_details'
|
|
12
|
+
autoload :AddressLine, 'newsmlg2/types/party_details'
|
|
13
|
+
autoload :AltId, 'newsmlg2/types/ids'
|
|
14
|
+
autoload :AltRep, 'newsmlg2/types/item_management'
|
|
15
|
+
autoload :ApproximateDateTimePropType, 'newsmlg2/types/approximate_date_time_prop_type'
|
|
16
|
+
autoload :DateOptTimePropType, 'newsmlg2/types/date_opt_time_prop_type'
|
|
17
|
+
autoload :DateTimeOrNullPropType, 'newsmlg2/types/date_time_or_null_prop_type'
|
|
18
|
+
autoload :DateTimePropType, 'newsmlg2/types/date_time_prop_type'
|
|
19
|
+
autoload :Area, 'newsmlg2/types/party_details'
|
|
20
|
+
autoload :Audience, 'newsmlg2/types/content_meta_types'
|
|
21
|
+
autoload :AudienceType, 'newsmlg2/types/content_meta_types'
|
|
22
|
+
autoload :Bag, 'newsmlg2/types/bag'
|
|
23
|
+
autoload :BlockType, 'newsmlg2/types/block_types'
|
|
24
|
+
autoload :Born, 'newsmlg2/types/party_details'
|
|
25
|
+
autoload :Br, 'newsmlg2/types/ruby_annotation'
|
|
26
|
+
autoload :Broader, 'newsmlg2/types/related_concept'
|
|
27
|
+
autoload :By, 'newsmlg2/types/content_meta_types'
|
|
28
|
+
autoload :Capacity, 'newsmlg2/types/poi'
|
|
29
|
+
autoload :Concept, 'newsmlg2/types/concept'
|
|
30
|
+
autoload :ConceptId, 'newsmlg2/types/concept_id'
|
|
31
|
+
autoload :ConceptIdType, 'newsmlg2/types/concept_id'
|
|
32
|
+
autoload :ConceptNameType, 'newsmlg2/types/concept_name_type'
|
|
33
|
+
autoload :ConceptType, 'newsmlg2/types/qual_prop_type'
|
|
34
|
+
autoload :Confirmation, 'newsmlg2/types/event_details'
|
|
35
|
+
autoload :ContactInfoType, 'newsmlg2/types/party_details'
|
|
36
|
+
autoload :ContentDescription, 'newsmlg2/types/content_meta_types'
|
|
37
|
+
autoload :CopyrightNotice, 'newsmlg2/types/rights'
|
|
38
|
+
autoload :Country, 'newsmlg2/types/party_details'
|
|
39
|
+
autoload :Creditline, 'newsmlg2/types/content_meta_types'
|
|
40
|
+
autoload :Dateline, 'newsmlg2/types/content_meta_types'
|
|
41
|
+
autoload :Definition, 'newsmlg2/types/block_types'
|
|
42
|
+
autoload :Details, 'newsmlg2/types/poi'
|
|
43
|
+
autoload :DigitalSourceType, 'newsmlg2/types/content_meta_types'
|
|
44
|
+
autoload :Died, 'newsmlg2/types/party_details'
|
|
45
|
+
autoload :Email, 'newsmlg2/types/party_details'
|
|
46
|
+
autoload :End, 'newsmlg2/types/event_details'
|
|
47
|
+
autoload :Event, 'newsmlg2/types/event_details'
|
|
48
|
+
autoload :EventDetails, 'newsmlg2/types/event_details'
|
|
49
|
+
autoload :EventDetailsLocation, 'newsmlg2/types/event_details'
|
|
50
|
+
autoload :EventDetailsSubject, 'newsmlg2/types/event_details'
|
|
51
|
+
autoload :EventDuration, 'newsmlg2/types/event_details'
|
|
52
|
+
autoload :EventNewsCoverage, 'newsmlg2/types/event_details'
|
|
53
|
+
autoload :Events, 'newsmlg2/types/event_details'
|
|
54
|
+
autoload :ExclAudience, 'newsmlg2/types/content_meta_types'
|
|
55
|
+
autoload :ExDate, 'newsmlg2/types/event_details'
|
|
56
|
+
autoload :ExRule, 'newsmlg2/types/event_details'
|
|
57
|
+
autoload :Facet, 'newsmlg2/types/facet'
|
|
58
|
+
autoload :FacetConcept, 'newsmlg2/types/related_concept'
|
|
59
|
+
autoload :Fax, 'newsmlg2/types/party_details'
|
|
60
|
+
autoload :FileName, 'newsmlg2/types/item_management'
|
|
61
|
+
autoload :Flex1ConceptPropType, 'newsmlg2/types/flex1_prop_type'
|
|
62
|
+
autoload :Flex1ExtPropType, 'newsmlg2/types/ext_property'
|
|
63
|
+
autoload :Flex1PartyPropType, 'newsmlg2/types/flex_party_prop_type'
|
|
64
|
+
autoload :Flex1PropType, 'newsmlg2/types/flex1_prop_type'
|
|
65
|
+
autoload :Flex1RolePropType, 'newsmlg2/types/flex1_prop_type'
|
|
66
|
+
autoload :Flex2ExtPropType, 'newsmlg2/types/ext_property'
|
|
67
|
+
autoload :FlexAuthorPropType, 'newsmlg2/types/flex_party_prop_type'
|
|
68
|
+
autoload :FlexGeoAreaPropType, 'newsmlg2/types/flex_location_prop_type'
|
|
69
|
+
autoload :FlexLocationPropType, 'newsmlg2/types/flex_location_prop_type'
|
|
70
|
+
autoload :FlexPartyPropType, 'newsmlg2/types/flex_party_prop_type'
|
|
71
|
+
autoload :FlexPersonPropType, 'newsmlg2/types/flex_party_prop_type'
|
|
72
|
+
autoload :FlexPOIPropType, 'newsmlg2/types/flex_location_prop_type'
|
|
73
|
+
autoload :FlexProp2Type, 'newsmlg2/types/flex_prop2_type'
|
|
74
|
+
autoload :FlexPropType, 'newsmlg2/types/flex_prop_type'
|
|
75
|
+
autoload :FlexRelatedConceptType, 'newsmlg2/types/related_concept'
|
|
76
|
+
autoload :FlexRelatedPropType, 'newsmlg2/types/flex_prop2_type'
|
|
77
|
+
autoload :Genre, 'newsmlg2/types/content_meta_types'
|
|
78
|
+
autoload :GeoAreaCircle, 'newsmlg2/types/geo'
|
|
79
|
+
autoload :GeoAreaDetails, 'newsmlg2/types/geo'
|
|
80
|
+
autoload :GeoAreaDissolved, 'newsmlg2/types/geo'
|
|
81
|
+
autoload :GeoAreaFounded, 'newsmlg2/types/geo'
|
|
82
|
+
autoload :GeoAreaLine, 'newsmlg2/types/geo'
|
|
83
|
+
autoload :GeoAreaPolygon, 'newsmlg2/types/geo'
|
|
84
|
+
autoload :GeoCoordinatesType, 'newsmlg2/types/geo'
|
|
85
|
+
autoload :Generator, 'newsmlg2/types/item_management'
|
|
86
|
+
autoload :HasInstrument, 'newsmlg2/types/party_details'
|
|
87
|
+
autoload :Hash, 'newsmlg2/types/ids'
|
|
88
|
+
autoload :Headline, 'newsmlg2/types/content_meta_types'
|
|
89
|
+
autoload :HierarchyInfo, 'newsmlg2/types/hierarchy_info'
|
|
90
|
+
autoload :Icon, 'newsmlg2/types/content_meta_types'
|
|
91
|
+
autoload :Im, 'newsmlg2/types/party_details'
|
|
92
|
+
autoload :IncomingFeedId, 'newsmlg2/types/item_management'
|
|
93
|
+
autoload :Inline, 'newsmlg2/types/inline_types'
|
|
94
|
+
autoload :IntlStringType, 'newsmlg2/types/intl_string_type'
|
|
95
|
+
autoload :IntlStringType2, 'newsmlg2/types/intl_string_type2'
|
|
96
|
+
autoload :Keyword, 'newsmlg2/types/content_meta_types'
|
|
97
|
+
autoload :Label1Type, 'newsmlg2/types/block_types'
|
|
98
|
+
autoload :Language, 'newsmlg2/types/content_meta_types'
|
|
99
|
+
autoload :LanguageName, 'newsmlg2/types/content_meta_types'
|
|
100
|
+
autoload :Link, 'newsmlg2/types/link'
|
|
101
|
+
autoload :Link1Type, 'newsmlg2/types/link'
|
|
102
|
+
autoload :Locality, 'newsmlg2/types/party_details'
|
|
103
|
+
autoload :MainConcept, 'newsmlg2/types/related_concept'
|
|
104
|
+
autoload :Narrower, 'newsmlg2/types/related_concept'
|
|
105
|
+
autoload :NewsCoverageStatus, 'newsmlg2/types/event_details'
|
|
106
|
+
autoload :Note, 'newsmlg2/types/block_types'
|
|
107
|
+
autoload :ObjectCreated, 'newsmlg2/types/object_details'
|
|
108
|
+
autoload :ObjectCeasedToExist, 'newsmlg2/types/object_details'
|
|
109
|
+
autoload :ObjectDetails, 'newsmlg2/types/object_details'
|
|
110
|
+
autoload :OccurStatus, 'newsmlg2/types/event_details'
|
|
111
|
+
autoload :OpenHours, 'newsmlg2/types/poi'
|
|
112
|
+
autoload :OrganisationDetails, 'newsmlg2/types/party_details'
|
|
113
|
+
autoload :OrganisationDissolved, 'newsmlg2/types/party_details'
|
|
114
|
+
autoload :OrganisationFounded, 'newsmlg2/types/party_details'
|
|
115
|
+
autoload :OrganisationLocation, 'newsmlg2/types/party_details'
|
|
116
|
+
autoload :Organiser, 'newsmlg2/types/event_details'
|
|
117
|
+
autoload :OrigRep, 'newsmlg2/types/item_management'
|
|
118
|
+
autoload :Participant, 'newsmlg2/types/event_details'
|
|
119
|
+
autoload :ParticipationRequirement, 'newsmlg2/types/event_details'
|
|
120
|
+
autoload :Party, 'newsmlg2/types/flex_party_prop_type'
|
|
121
|
+
autoload :PersonDetails, 'newsmlg2/types/party_details'
|
|
122
|
+
autoload :Phone, 'newsmlg2/types/party_details'
|
|
123
|
+
autoload :POICeasedToExist, 'newsmlg2/types/poi'
|
|
124
|
+
autoload :POICreated, 'newsmlg2/types/poi'
|
|
125
|
+
autoload :POIDetails, 'newsmlg2/types/poi'
|
|
126
|
+
autoload :Position, 'newsmlg2/types/geo'
|
|
127
|
+
autoload :PostalCode, 'newsmlg2/types/party_details'
|
|
128
|
+
autoload :QCodePropType, 'newsmlg2/types/qcode_prop_type'
|
|
129
|
+
autoload :QualPropType, 'newsmlg2/types/qual_prop_type'
|
|
130
|
+
autoload :QualRelPropType, 'newsmlg2/types/qual_rel_prop_type'
|
|
131
|
+
autoload :Rb, 'newsmlg2/types/ruby_annotation'
|
|
132
|
+
autoload :RDate, 'newsmlg2/types/event_details'
|
|
133
|
+
autoload :Rating, 'newsmlg2/types/content_meta_types'
|
|
134
|
+
autoload :Registration, 'newsmlg2/types/event_details'
|
|
135
|
+
autoload :Related, 'newsmlg2/types/related_concept'
|
|
136
|
+
autoload :RelatedConceptType, 'newsmlg2/types/related_concept'
|
|
137
|
+
autoload :RemoteInfo, 'newsmlg2/types/link'
|
|
138
|
+
autoload :RightsBlockType, 'newsmlg2/types/rights'
|
|
139
|
+
autoload :RightsExpressionData, 'newsmlg2/types/rights'
|
|
140
|
+
autoload :RightsExpressionXML, 'newsmlg2/types/rights'
|
|
141
|
+
autoload :RightsInfo, 'newsmlg2/types/rights'
|
|
142
|
+
autoload :Rp, 'newsmlg2/types/ruby_annotation'
|
|
143
|
+
autoload :RRule, 'newsmlg2/types/event_details'
|
|
144
|
+
autoload :Rt, 'newsmlg2/types/ruby_annotation'
|
|
145
|
+
autoload :Ruby, 'newsmlg2/types/ruby_annotation'
|
|
146
|
+
autoload :SameAs, 'newsmlg2/types/same_as'
|
|
147
|
+
autoload :SameAsType, 'newsmlg2/types/same_as'
|
|
148
|
+
autoload :Signal, 'newsmlg2/types/item_management'
|
|
149
|
+
autoload :Slugline, 'newsmlg2/types/content_meta_types'
|
|
150
|
+
autoload :Span, 'newsmlg2/types/inline_types'
|
|
151
|
+
autoload :Start, 'newsmlg2/types/event_details'
|
|
152
|
+
autoload :Subject, 'newsmlg2/types/content_meta_types'
|
|
153
|
+
autoload :TruncatedDateTimePropType, 'newsmlg2/types/truncated_date_time_prop_type'
|
|
154
|
+
autoload :Urgency, 'newsmlg2/types/content_meta_types'
|
|
155
|
+
autoload :UsageTerms, 'newsmlg2/types/rights'
|
|
156
|
+
autoload :UserInteraction, 'newsmlg2/types/content_meta_types'
|
|
157
|
+
autoload :VersionedStringType, 'newsmlg2/types/versioned_string_type'
|
|
158
|
+
autoload :Web, 'newsmlg2/types/party_details'
|
|
159
|
+
autoload :WorldRegion, 'newsmlg2/types/party_details'
|
|
160
|
+
autoload :XmlBase, 'newsmlg2/types/xml_base'
|
|
161
|
+
autoload :XmlLang, 'newsmlg2/types/xml_lang'
|
|
162
|
+
|
|
163
|
+
# python-newsmlg2 API parity aliases.
|
|
164
|
+
Name = ConceptNameType
|
|
165
|
+
end
|
|
166
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Newsmlg2
|
|
4
|
+
# QCode <-> URI conversion using a document's catalogs.
|
|
5
|
+
module Utils
|
|
6
|
+
module_function
|
|
7
|
+
|
|
8
|
+
# Expands a qcode (e.g. "ninat:text") to its full concept URI using the
|
|
9
|
+
# schemes declared in the document's catalogs.
|
|
10
|
+
#
|
|
11
|
+
# @raise [Newsmlg2::AliasNotFoundInCatalogs]
|
|
12
|
+
def qcode_to_uri(qcode, store_or_document)
|
|
13
|
+
store = catalog_store_for(store_or_document)
|
|
14
|
+
alias_name, code = qcode.split(':', 2)
|
|
15
|
+
raise ArgumentError, "not a qcode: #{qcode.inspect}" if code.nil?
|
|
16
|
+
|
|
17
|
+
store.get_scheme_for_alias(alias_name).uri + code
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Compresses a concept URI back to a qcode using the schemes declared in
|
|
21
|
+
# the document's catalogs.
|
|
22
|
+
#
|
|
23
|
+
# @raise [Newsmlg2::UriNotFoundInCatalogs]
|
|
24
|
+
def uri_to_qcode(uri, store_or_document)
|
|
25
|
+
store = catalog_store_for(store_or_document)
|
|
26
|
+
idx = uri.rindex('/')
|
|
27
|
+
raise ArgumentError, "not a concept URI: #{uri.inspect}" unless idx
|
|
28
|
+
|
|
29
|
+
scheme_uri = uri[0..idx]
|
|
30
|
+
code = uri[(idx + 1)..]
|
|
31
|
+
"#{store.get_scheme_for_uri(scheme_uri).alias_attr}:#{code}"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def catalog_store_for(store_or_document)
|
|
35
|
+
if store_or_document.is_a?(CatalogStore)
|
|
36
|
+
store_or_document
|
|
37
|
+
else
|
|
38
|
+
store_or_document.catalog_store
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
data/lib/newsmlg2.rb
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'lutaml/model'
|
|
4
|
+
|
|
5
|
+
# Newsmlg2 is a lutaml-model-based object model for IPTC NewsML-G2 (NAR):
|
|
6
|
+
# parse, manipulate, build and serialize NewsML-G2 XML with round-trip
|
|
7
|
+
# fidelity. Targets specification version 2.35, power conformance.
|
|
8
|
+
module Newsmlg2
|
|
9
|
+
# The NewsML-G2 specification version this library models; used as the
|
|
10
|
+
# default standardversion of serialized items.
|
|
11
|
+
SPEC_VERSION = '2.35'
|
|
12
|
+
|
|
13
|
+
autoload :VERSION, 'newsmlg2/version'
|
|
14
|
+
|
|
15
|
+
# Shared mixin groups (XSD attribute groups and element groups).
|
|
16
|
+
autoload :Base, 'newsmlg2/base'
|
|
17
|
+
|
|
18
|
+
# Shared value types (XSD complex types usable as element payloads).
|
|
19
|
+
autoload :Types, 'newsmlg2/types'
|
|
20
|
+
|
|
21
|
+
# Item model classes (XSD item types and their structural children).
|
|
22
|
+
autoload :Action, 'newsmlg2/items/any_item'
|
|
23
|
+
autoload :AltLoc, 'newsmlg2/items/news_item'
|
|
24
|
+
autoload :AnyItem, 'newsmlg2/items/any_item'
|
|
25
|
+
autoload :Assert, 'newsmlg2/items/any_item'
|
|
26
|
+
autoload :AssignedTo, 'newsmlg2/items/planning_item'
|
|
27
|
+
autoload :CatalogContainer, 'newsmlg2/items/catalog_item'
|
|
28
|
+
autoload :CatalogItem, 'newsmlg2/items/catalog_item'
|
|
29
|
+
autoload :Channel, 'newsmlg2/items/news_item'
|
|
30
|
+
autoload :ConceptItem, 'newsmlg2/items/concept_item'
|
|
31
|
+
autoload :ConceptRef, 'newsmlg2/items/package_item'
|
|
32
|
+
autoload :ConceptSet, 'newsmlg2/items/knowledge_item'
|
|
33
|
+
autoload :ContentMeta, 'newsmlg2/items/content_meta'
|
|
34
|
+
autoload :ContentMetaAcD, 'newsmlg2/items/content_meta'
|
|
35
|
+
autoload :ContentMetaCat, 'newsmlg2/items/content_meta'
|
|
36
|
+
autoload :ContentSet, 'newsmlg2/items/news_item'
|
|
37
|
+
autoload :DeliveredItemRef, 'newsmlg2/items/planning_item'
|
|
38
|
+
autoload :Delivery, 'newsmlg2/items/planning_item'
|
|
39
|
+
autoload :DerivedFrom, 'newsmlg2/items/any_item'
|
|
40
|
+
autoload :DerivedFromValue, 'newsmlg2/items/any_item'
|
|
41
|
+
autoload :Destination, 'newsmlg2/items/news_message'
|
|
42
|
+
autoload :G2ContentType, 'newsmlg2/items/planning_item'
|
|
43
|
+
autoload :Group, 'newsmlg2/items/package_item'
|
|
44
|
+
autoload :GroupRef, 'newsmlg2/items/package_item'
|
|
45
|
+
autoload :GroupSet, 'newsmlg2/items/package_item'
|
|
46
|
+
autoload :Header, 'newsmlg2/items/news_message'
|
|
47
|
+
autoload :Hop, 'newsmlg2/items/any_item'
|
|
48
|
+
autoload :HopHistory, 'newsmlg2/items/any_item'
|
|
49
|
+
autoload :InlineData, 'newsmlg2/items/news_item'
|
|
50
|
+
autoload :InlineRef, 'newsmlg2/items/any_item'
|
|
51
|
+
autoload :InlineXML, 'newsmlg2/items/news_item'
|
|
52
|
+
autoload :ItemCount, 'newsmlg2/items/planning_item'
|
|
53
|
+
autoload :ItemMeta, 'newsmlg2/items/any_item'
|
|
54
|
+
autoload :ItemRef, 'newsmlg2/items/item_ref'
|
|
55
|
+
autoload :ItemSet, 'newsmlg2/items/news_message'
|
|
56
|
+
autoload :KnowledgeItem, 'newsmlg2/items/knowledge_item'
|
|
57
|
+
autoload :MessageChannel, 'newsmlg2/items/news_message'
|
|
58
|
+
autoload :MessageTimestamp, 'newsmlg2/items/news_message'
|
|
59
|
+
autoload :NewsContentCharacteristicsElement, 'newsmlg2/items/planning_item'
|
|
60
|
+
autoload :NewsCoverage, 'newsmlg2/items/planning_item'
|
|
61
|
+
autoload :NewsCoverageSet, 'newsmlg2/items/planning_item'
|
|
62
|
+
autoload :NewsItem, 'newsmlg2/items/news_item'
|
|
63
|
+
autoload :NewsMessage, 'newsmlg2/items/news_message'
|
|
64
|
+
autoload :Origin, 'newsmlg2/items/news_message'
|
|
65
|
+
autoload :PackageItem, 'newsmlg2/items/package_item'
|
|
66
|
+
autoload :PartMeta, 'newsmlg2/items/part_meta'
|
|
67
|
+
autoload :PartMetaRole, 'newsmlg2/items/part_meta'
|
|
68
|
+
autoload :Planning, 'newsmlg2/items/planning_item'
|
|
69
|
+
autoload :PlanningItem, 'newsmlg2/items/planning_item'
|
|
70
|
+
autoload :Priority, 'newsmlg2/items/news_message'
|
|
71
|
+
autoload :PubHistory, 'newsmlg2/items/any_item'
|
|
72
|
+
autoload :Published, 'newsmlg2/items/any_item'
|
|
73
|
+
autoload :RegionDelim, 'newsmlg2/items/part_meta'
|
|
74
|
+
autoload :RemoteContent, 'newsmlg2/items/news_item'
|
|
75
|
+
autoload :Scheduled, 'newsmlg2/items/planning_item'
|
|
76
|
+
autoload :SchemeMeta, 'newsmlg2/items/knowledge_item'
|
|
77
|
+
autoload :Sender, 'newsmlg2/items/news_message'
|
|
78
|
+
autoload :Sent, 'newsmlg2/items/news_message'
|
|
79
|
+
autoload :StringType, 'newsmlg2/items/news_message'
|
|
80
|
+
autoload :TimeDelim, 'newsmlg2/items/part_meta'
|
|
81
|
+
autoload :Timestamp, 'newsmlg2/items/any_item'
|
|
82
|
+
|
|
83
|
+
# Catalog subsystem (qcode resolution).
|
|
84
|
+
autoload :Catalog, 'newsmlg2/catalog'
|
|
85
|
+
autoload :CatalogCache, 'newsmlg2/catalog_cache'
|
|
86
|
+
autoload :CatalogRef, 'newsmlg2/catalog_ref'
|
|
87
|
+
autoload :CatalogStore, 'newsmlg2/catalog_store'
|
|
88
|
+
autoload :Scheme, 'newsmlg2/scheme'
|
|
89
|
+
autoload :SameAsScheme, 'newsmlg2/same_as_scheme'
|
|
90
|
+
|
|
91
|
+
# Document entry point and support.
|
|
92
|
+
autoload :AliasNotFoundInCatalogs, 'newsmlg2/errors'
|
|
93
|
+
autoload :Builder, 'newsmlg2/builder'
|
|
94
|
+
autoload :Configuration, 'newsmlg2/configuration'
|
|
95
|
+
autoload :Document, 'newsmlg2/document'
|
|
96
|
+
autoload :Error, 'newsmlg2/errors'
|
|
97
|
+
autoload :I18n, 'newsmlg2/i18n'
|
|
98
|
+
autoload :MissingGuidError, 'newsmlg2/errors'
|
|
99
|
+
autoload :NarModel, 'newsmlg2/nar_model'
|
|
100
|
+
autoload :NarNamespace, 'newsmlg2/nar_namespace'
|
|
101
|
+
autoload :NitfNamespace, 'newsmlg2/nitf_namespace'
|
|
102
|
+
autoload :UnknownRootElement, 'newsmlg2/errors'
|
|
103
|
+
autoload :UriNotFoundInCatalogs, 'newsmlg2/errors'
|
|
104
|
+
autoload :Utils, 'newsmlg2/utils'
|
|
105
|
+
|
|
106
|
+
class << self
|
|
107
|
+
# Parses NewsML-G2 XML (any item type or a newsMessage envelope).
|
|
108
|
+
#
|
|
109
|
+
# @return [Newsmlg2::Document]
|
|
110
|
+
def parse(xml)
|
|
111
|
+
Document.parse(xml)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Parses a NewsML-G2 XML file.
|
|
115
|
+
#
|
|
116
|
+
# @return [Newsmlg2::Document]
|
|
117
|
+
def parse_file(path)
|
|
118
|
+
Document.parse_file(path)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Expands a qcode (e.g. "ninat:text") to its full concept URI using the
|
|
122
|
+
# catalogs registered with the given document.
|
|
123
|
+
#
|
|
124
|
+
# @raise [Newsmlg2::AliasNotFoundInCatalogs]
|
|
125
|
+
def qcode_to_uri(qcode, document)
|
|
126
|
+
Utils.qcode_to_uri(qcode, document)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Compresses a concept URI back to a qcode using the given document's
|
|
130
|
+
# catalogs.
|
|
131
|
+
#
|
|
132
|
+
# @raise [Newsmlg2::UriNotFoundInCatalogs]
|
|
133
|
+
def uri_to_qcode(uri, document)
|
|
134
|
+
Utils.uri_to_qcode(uri, document)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Builder DSL entry points (see Newsmlg2::Builder).
|
|
138
|
+
def build_item(klass, **attributes, &)
|
|
139
|
+
Builder.build(klass, attributes, &)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def build_news_item(**attributes, &)
|
|
143
|
+
Builder.build_news_item(**attributes, &)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def build_package_item(**attributes, &)
|
|
147
|
+
Builder.build_package_item(**attributes, &)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def build_concept_item(**attributes, &)
|
|
151
|
+
Builder.build_concept_item(**attributes, &)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def build_knowledge_item(**attributes, &)
|
|
155
|
+
Builder.build_knowledge_item(**attributes, &)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def build_catalog_item(**attributes, &)
|
|
159
|
+
Builder.build_catalog_item(**attributes, &)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def build_planning_item(**attributes, &)
|
|
163
|
+
Builder.build_planning_item(**attributes, &)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def build_news_message(**attributes, &)
|
|
167
|
+
Builder.build_news_message(**attributes, &)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Registry: element id -> model class. The single source of truth for
|
|
172
|
+
# root-element dispatch and itemSet item resolution (plurimath/mml
|
|
173
|
+
# pattern); library code never compares element-name strings itself.
|
|
174
|
+
Configuration.register_model(NewsItem, id: :newsItem)
|
|
175
|
+
Configuration.register_model(PackageItem, id: :packageItem)
|
|
176
|
+
Configuration.register_model(ConceptItem, id: :conceptItem)
|
|
177
|
+
Configuration.register_model(KnowledgeItem, id: :knowledgeItem)
|
|
178
|
+
Configuration.register_model(CatalogItem, id: :catalogItem)
|
|
179
|
+
Configuration.register_model(PlanningItem, id: :planningItem)
|
|
180
|
+
Configuration.register_model(NewsMessage, id: :newsMessage)
|
|
181
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Baseline: parse + serialize timings over the official IPTC examples.
|
|
4
|
+
# `rake performance:baseline` writes tmp/performance-baseline.json;
|
|
5
|
+
# `rake performance:compare` compares the current run against it (skipped
|
|
6
|
+
# with a message when no baseline exists).
|
|
7
|
+
namespace :performance do
|
|
8
|
+
ROOT = File.expand_path('../..', __dir__)
|
|
9
|
+
EXAMPLES = File.join(ROOT, 'spec/fixtures/iptc/examples')
|
|
10
|
+
|
|
11
|
+
def run_benchmarks
|
|
12
|
+
require 'newsmlg2'
|
|
13
|
+
results = {}
|
|
14
|
+
Dir[File.join(EXAMPLES, '*.xml')].each do |path|
|
|
15
|
+
results[File.basename(path)] = benchmark_document(path)
|
|
16
|
+
end
|
|
17
|
+
results
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def benchmark_document(path)
|
|
21
|
+
source = File.read(path)
|
|
22
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
23
|
+
begin
|
|
24
|
+
Newsmlg2.parse(source).to_xml
|
|
25
|
+
rescue StandardError
|
|
26
|
+
nil
|
|
27
|
+
end
|
|
28
|
+
(Process.clock_gettime(Process::CLOCK_MONOTONIC) - start).round(6)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def baseline_path
|
|
32
|
+
File.join(ROOT, 'tmp/performance-baseline.json')
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
desc 'Write a performance baseline'
|
|
36
|
+
task :baseline do
|
|
37
|
+
require 'json'
|
|
38
|
+
results = run_benchmarks
|
|
39
|
+
FileUtils.mkdir_p(File.dirname(baseline_path))
|
|
40
|
+
File.write(baseline_path, JSON.pretty_generate(results))
|
|
41
|
+
puts "Baseline written: #{baseline_path} (#{results.size} documents)"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
desc 'Compare current performance against the baseline'
|
|
45
|
+
task :compare do
|
|
46
|
+
require 'json'
|
|
47
|
+
unless File.exist?(baseline_path)
|
|
48
|
+
puts "No baseline at #{baseline_path} — run `rake performance:baseline` first."
|
|
49
|
+
next
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
baseline = JSON.parse(File.read(baseline_path))
|
|
53
|
+
current = run_benchmarks
|
|
54
|
+
slower = []
|
|
55
|
+
current.each do |name, seconds|
|
|
56
|
+
base = baseline[name]
|
|
57
|
+
next unless base
|
|
58
|
+
|
|
59
|
+
ratio = seconds / base
|
|
60
|
+
slower << [name, base, seconds, ratio] if ratio > 1.5
|
|
61
|
+
end
|
|
62
|
+
if slower.empty?
|
|
63
|
+
puts "No document regressed by more than 50% (#{current.size} documents)."
|
|
64
|
+
else
|
|
65
|
+
slower.sort_by { |(_, _, _, ratio)| -ratio }.first(10).each do |name, base, now, ratio|
|
|
66
|
+
warn format('%<name>s: %<base>.4fs -> %<now>.4fs (%<ratio>.2fx)', name: name, base: base, now: now,
|
|
67
|
+
ratio: ratio)
|
|
68
|
+
end
|
|
69
|
+
raise 'performance regression detected'
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
data/newsmlg2.gemspec
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/newsmlg2/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'newsmlg2'
|
|
7
|
+
spec.version = Newsmlg2::VERSION
|
|
8
|
+
spec.authors = ['Ribose Inc.']
|
|
9
|
+
spec.email = ['open.source@ribose.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'NewsML-G2 — IPTC News Architecture (NewsML-G2) for Ruby.'
|
|
12
|
+
spec.description = 'Newsmlg2 provides a lutaml-model-based Ruby object model for IPTC ' \
|
|
13
|
+
'NewsML-G2 (NAR). Parse, manipulate, build and serialize NewsML-G2 ' \
|
|
14
|
+
'XML with full round-trip fidelity, including a builder DSL.'
|
|
15
|
+
spec.homepage = 'https://github.com/lutaml/newsmlg2-ruby'
|
|
16
|
+
spec.license = 'BSD-2-Clause'
|
|
17
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 3.3.0')
|
|
18
|
+
|
|
19
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
20
|
+
spec.metadata['source_code_uri'] = 'https://github.com/lutaml/newsmlg2-ruby'
|
|
21
|
+
spec.metadata['changelog_uri'] = 'https://github.com/lutaml/newsmlg2-ruby/blob/main/CHANGELOG.md'
|
|
22
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
23
|
+
|
|
24
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
25
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
26
|
+
f.match(%r{^(test|spec|features)/})
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
spec.bindir = 'exe'
|
|
30
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
31
|
+
spec.require_paths = ['lib']
|
|
32
|
+
|
|
33
|
+
spec.add_dependency 'lutaml-model', '~> 0.8.0'
|
|
34
|
+
end
|