bibframe_ruby 0.2.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 656c3e0e3d78aa14eca5596e153c7aada8a5a89fb6645bed67ed0aba0b9a49b8
4
- data.tar.gz: 64dead66a959b38cbba57831c898a00807039266af64bcb09f4a2928c1a27fda
3
+ metadata.gz: c56b203ce79a9b28d23e6cdb460b640ae3a45e57e6d58ca63f62a99cb5db017a
4
+ data.tar.gz: 62d1d77bb4085fbaf41dff1364defbb18490a9e81931696ee49fba7f2f760a4e
5
5
  SHA512:
6
- metadata.gz: '0957c3c819f85e626b24225efd65bdee191b884b91bcb9147e7b21bb1de25eee54076fa1017e6911af1d192f6c6f0fc231a8e55795aa3bb610443dab8658cdf0'
7
- data.tar.gz: d8f596aa28c8873cfa68d24340f350bbdb0846b7e210c23fe1c92c59049ed026dcf34ffe0f736fea7e7715f422750ff42caf08d85f973716a24126d00fc8ee96
6
+ metadata.gz: 3cf43245857c53ac5c7635456da9d6c4741ff8a3e7b3ae68474ca85b3d82ee6a258af49b553c7560c3e9f3d116b3b584ac3b7ab4d9d48cb1c1a1a080a6cc79b1
7
+ data.tar.gz: 66537e8a3d3d08098a09f4626834e63d8605a5afd4a7adb6dd3fef76e55b5c25588c54a38238829373bc6c88586e73aec6b262f39cb7e3bab604ab70949c8b8f
data/README.md CHANGED
@@ -226,11 +226,29 @@ agent.is_a?(BibframeRuby::Resource)
226
226
  # => true
227
227
  ```
228
228
 
229
+ ### Serializing to RDF
230
+
231
+ Serialize a graph or individual resource back to JSON-LD or Turtle:
232
+
233
+ ```ruby
234
+ # Serialize the entire graph to JSON-LD (default)
235
+ puts graph.to_rdf
236
+
237
+ # Serialize to Turtle
238
+ puts graph.to_rdf(format: :turtle)
239
+
240
+ # Serialize a single resource (includes its nested blank nodes)
241
+ puts work.to_rdf
242
+ puts work.to_rdf(format: :turtle)
243
+ ```
244
+
245
+ Output includes BIBFRAME-aware prefixes (`bf:`, `bflc:`, `rdfs:`, etc.) for readable output.
246
+
229
247
  ## Model Reference
230
248
 
231
249
  | Class | Accessors |
232
250
  |-------|-----------|
233
- | `Resource` | `id`, `types`, `properties`, `[]`, `[]=` |
251
+ | `Resource` | `id`, `types`, `properties`, `[]`, `[]=`, `to_rdf` |
234
252
  | `Work` | `title`, `contributions`, `instances`, `language`, `subjects`, `genre_forms`, `summary`, `classifications`, `relations` |
235
253
  | `Instance` | `title`, `work`, `identifiers`, `extent`, `carrier`, `media`, `provision_activity`, `edition_statement`, `dimensions`, `publication_statement`, `items` |
236
254
  | `Hub` | `title`, `contributions`, `language`, `identifiers`, `relations`, `label` |
@@ -1,28 +1,59 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "json"
4
+
3
5
  # BibframeRuby::Graph: Container for parsed BIBFRAME resources with typed collection accessors
4
6
  module BibframeRuby
5
7
  # Container returned by BibframeRuby.parse that holds all parsed resources with typed collection accessors.
6
8
  class Graph
7
- attr_reader :works, :instances, :items, :hubs, :resources
9
+ attr_reader :works, :instances, :items, :hubs, :resources, :rdf_graph
10
+
11
+ WRITER_MAP = {
12
+ jsonld: JSON::LD::Writer,
13
+ turtle: RDF::Turtle::Writer
14
+ }.freeze
15
+
16
+ PREFIXES = {
17
+ bf: "http://id.loc.gov/ontologies/bibframe/",
18
+ bflc: "http://id.loc.gov/ontologies/bflc/",
19
+ rdfs: "http://www.w3.org/2000/01/rdf-schema#",
20
+ rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
21
+ xsd: "http://www.w3.org/2001/XMLSchema#"
22
+ }.freeze
8
23
 
9
- def initialize(works:, instances:, items:, resources:, hubs: [])
24
+ def initialize(works:, instances:, items:, resources:, hubs: [], rdf_graph: nil)
10
25
  @works = works
11
26
  @instances = instances
12
27
  @items = items
13
28
  @hubs = hubs
14
29
  @resources = resources
30
+ @rdf_graph = rdf_graph
31
+ end
32
+
33
+ def to_rdf(format: :jsonld)
34
+ writer_class = WRITER_MAP.fetch(format) do
35
+ raise BibframeRuby::Error, "Unsupported serialization format: #{format}"
36
+ end
37
+
38
+ writer_class.buffer(prefixes: PREFIXES.dup) { |w| @rdf_graph.each_statement { |s| w << s } }
15
39
  end
16
40
 
17
41
  def self.from_rdf(rdf_graph)
18
42
  result = GraphBuilder.new(rdf_graph).build
19
- new(
43
+
44
+ graph = new(
20
45
  works: result[:works],
21
46
  instances: result[:instances],
22
47
  items: result[:items],
23
48
  hubs: result[:hubs],
24
- resources: result[:resources].values
49
+ resources: result[:resources].values,
50
+ rdf_graph: rdf_graph
25
51
  )
52
+
53
+ # Set back-references so resources can serialize themselves
54
+ result[:resources].each_value { |r| r.rdf_graph = rdf_graph }
55
+
56
+ graph
26
57
  end
27
58
  end
28
59
  end
@@ -1,16 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "set"
4
+
3
5
  # BibframeRuby::Resource: Base class for all BIBFRAME resource types
4
6
  module BibframeRuby
5
7
  # Base class for all BIBFRAME resources. Provides URI identity, type tracking, and hash-style property access.
6
8
  class Resource
7
9
  attr_reader :id, :types
8
- attr_accessor :properties
10
+ attr_accessor :properties, :rdf_graph
9
11
 
10
12
  def initialize(id: nil, types: [], properties: {})
11
13
  @id = id
12
14
  @types = types
13
15
  @properties = properties
16
+ @rdf_graph = nil
14
17
  end
15
18
 
16
19
  def [](key)
@@ -20,5 +23,32 @@ module BibframeRuby
20
23
  def []=(key, value)
21
24
  @properties[key.to_s] = value
22
25
  end
26
+
27
+ def to_rdf(format: :jsonld)
28
+ raise BibframeRuby::Error, "Unsupported serialization format: #{format}" unless Graph::WRITER_MAP.key?(format)
29
+ raise BibframeRuby::Error, "No RDF graph available for serialization" unless @rdf_graph && @id
30
+
31
+ sub_graph = extract_sub_graph
32
+ Graph::WRITER_MAP[format].buffer(prefixes: Graph::PREFIXES.dup) { |w| sub_graph.each_statement { |s| w << s } }
33
+ end
34
+
35
+ private
36
+
37
+ def extract_sub_graph
38
+ sub_graph = RDF::Graph.new
39
+ visited = Set.new
40
+ collect_triples(RDF::URI(@id), visited, sub_graph)
41
+ sub_graph
42
+ end
43
+
44
+ def collect_triples(subject, visited, sub_graph)
45
+ return if visited.include?(subject)
46
+
47
+ visited << subject
48
+ @rdf_graph.query({subject: subject}).each do |stmt|
49
+ sub_graph << stmt
50
+ collect_triples(stmt.object, visited, sub_graph) if stmt.object.is_a?(RDF::Node)
51
+ end
52
+ end
23
53
  end
24
54
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  # BibframeRuby::VERSION: Gem version constant
4
4
  module BibframeRuby
5
- VERSION = "0.2.0"
5
+ VERSION = "0.2.1"
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bibframe_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Collier