rdfobjects 0.6.6 → 0.7.0

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.
data/README CHANGED
@@ -53,15 +53,25 @@ Usage:
53
53
 
54
54
  => "en"
55
55
 
56
- To relate a resource to another URI you can use #.resource - it will accept full uri strings, safe curies or other RDFObject::Resource objects
56
+ To relate a resource to another URI you can use #.relate - it will accept full uri strings, safe curies or other RDFObject::Resource objects
57
57
 
58
58
  >> resource.relate("[skos:closeMatch]", "http://dbpedia.org/resource/Category:Semantic_Web")
59
59
 
60
60
  => [#<RDFObject::Resource uri="http://stitch.cs.vu.nl/vocabularies/rameau/ark:/12148/cb14521343b">, #<RDFObject::Resource uri="http://dbpedia.org/resource/Category:Semantic_Web">]
61
61
 
62
- RDFObject::Resources sort of act as singletons
62
+ These relationships are actually replaced with RDFObject::ResourceReference objects (to prevent massive recursion errors). To access the actual Resource object, use:
63
63
 
64
- >> r1 = Resource.new('http://ex.org/ex/1234')
64
+ >> resource["[skos:closeMatch]"].first.resource
65
+
66
+ => #<RDFObject::Resource uri="http://stitch.cs.vu.nl/vocabularies/rameau/ark:/12148/cb14521343b">
67
+
68
+ In order to be sure you are always asserting against the same object, use RDFObject::Collection objects to manage your Resources.
69
+
70
+ >> collection = Collection.new
71
+
72
+ => {}
73
+
74
+ >> r1 = collection.find_or_create('http://ex.org/ex/1234')
65
75
 
66
76
  => #<RDFObject::Resource uri="http://ex.org/ex/1234">
67
77
 
@@ -69,7 +79,7 @@ Usage:
69
79
 
70
80
  => 8996290
71
81
 
72
- >> r2 = Resource.new('http://ex.org/ex/1234')
82
+ >> r2 = collection.find_or_create('http://ex.org/ex/1234')
73
83
 
74
84
  => #<RDFObject::Resource uri="http://ex.org/ex/1234">
75
85
 
@@ -77,38 +87,46 @@ Usage:
77
87
 
78
88
  => 8996290
79
89
 
80
- So relationships and assertions are always applied to the same object. These are managed in the RDFObject::Resource class:
90
+ So relationships and assertions are always applied to the same objects.
81
91
 
82
- >> Resource.instances
92
+ You can delete a single resource:
83
93
 
84
- => {"http://ex.org/ex/1234"=>#<RDFObject::Resource uri="http://ex.org/ex/1234">}
94
+ >> collection.remove(r1)
85
95
 
86
- To override this behavior (i.e. to create another object with the same URI), pass the :force argument:
96
+ >> collection
97
+ => {}
87
98
 
88
- >> r2 = Resource.new('http://ex.org/ex/1234', :force)
99
+ There is also a convenience method on RDFObject::Collection to help find particular resources by predicate:
89
100
 
90
- => #<RDFObject::Resource uri="http://ex.org/ex/1234">
101
+ >> resources_with_types = collection.find_by_predicate("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
91
102
 
92
- >> r2.object_id
103
+ And to find resources by predicate and object:
93
104
 
94
- => 8996310
105
+ >> resources_i_want = collection.find_by_predicate_and_object("http://www.w3.org/2004/02/skos/core#closeMatch", "http://stitch.cs.vu.nl/vocabularies/rameau/ark:/12148/cb145537755")
95
106
 
96
- You can delete a single resource:
107
+ Both these return RDFObject::Collection objects with your matches. Changes to resources in these collections also affect the resource in original collection.
97
108
 
98
- >> Resource.remove(r1)
109
+ There are also parsers for ntriples, rdf/xml, RSS 1.0, RDFa, and JSON. Parsers return a RDFObject::Collection with all of the resources discovered in the RDF source.
99
110
 
100
- >> Resource.instances
101
- => {}
102
-
103
- Or clear the entire hash:
111
+ >> resources = Parser.parse(open('lcsh.nt').read)
104
112
 
105
- >> Resource.reset!
113
+ >> resources.values.first
106
114
 
107
- There are also parsers for ntriples, rdf/xml, RSS 1.0, RDFa, and JSON.
115
+ => #<RDFObject::Resource n0={"altLabel"=>"Lichen ruber planus", "inScheme"=>[#<RDFObject::Resource uri="http://id.loc.gov/authorities#conceptScheme">, #<RDFObject::Resource uri="http://id.loc.gov/authorities#topicalTerms">], "prefLabel"=>"Lichen planus"}, n1={"sameAs"=>#<RDFObject::Resource uri="info:lc/authorities/sh85076767">}, uri="http://id.loc.gov/authorities/sh85076767#concept", n2={"modified"=>#<DateTime: 211644344801/86400,-1/6,2299161>}, rdf={"type"=>#<RDFObject::Resource uri="http://www.w3.org/2004/02/skos/core#Concept">}>
108
116
 
109
- >> resources = Parser.parse(open('lcsh.nt').read)
117
+ There are serializers for RDF/XML and ntriples. Both resources and collections can be serialized.
110
118
 
111
- >> resources.first
119
+ >> resource.to_xml
112
120
 
113
- => #<RDFObject::Resource n0={"altLabel"=>"Lichen ruber planus", "inScheme"=>[#<RDFObject::Resource uri="http://id.loc.gov/authorities#conceptScheme">, #<RDFObject::Resource uri="http://id.loc.gov/authorities#topicalTerms">], "prefLabel"=>"Lichen planus"}, n1={"sameAs"=>#<RDFObject::Resource uri="info:lc/authorities/sh85076767">}, uri="http://id.loc.gov/authorities/sh85076767#concept", n2={"modified"=>#<DateTime: 211644344801/86400,-1/6,2299161>}, rdf={"type"=>#<RDFObject::Resource uri="http://www.w3.org/2004/02/skos/core#Concept">}>
121
+ => "<rdf:RDF xmlns:n0="http://www.w3.org/2004/02/skos/core#" xmlns:n1="http://www.w3.org/2002/07/owl#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:n2="http://purl.org/dc/terms/"><rdf:Description rdf:about="http://id.loc.gov/authorities/sh85076767#concept"><n0:altLabel>Lichen ruber planus</n0:altLabel><n0:inScheme><rdf:Description rdf:about="http://id.loc.gov/authorities#conceptScheme"></rdf:Description></n0:inScheme><n0:inScheme><rdf:Description rdf:about="http://id.loc.gov/authorities#topicalTerms"></rdf:Description></n0:inScheme><n0:prefLabel>Lichen planus</n0:prefLabel><n1:sameAs><rdf:Description rdf:about="info:lc/authorities/sh85076767"></rdf:Description></n1:sameAs><n2:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">1994-08-22T15:46:41-04:00</n2:modified><rdf:type><rdf:Description rdf:about="http://www.w3.org/2004/02/skos/core#Concept"></rdf:Description></rdf:type></rdf:Description></rdf:RDF>"
122
+
123
+ >> collection.to_xml
124
+
125
+ >> resource.to_ntriples
126
+
127
+ => "<http://id.loc.gov/authorities/sh85076767#concept> <http://www.w3.org/2004/02/skos/core#altLabel> "Lichen ruber planus"@en.\n<http://id.loc.gov/authorities/sh85076767#concept> <http://www.w3.org/2004/02/skos/core#inScheme> <http://id.loc.gov/authorities#conceptScheme>.\n<http://id.loc.gov/authorities/sh85076767#concept> <http://www.w3.org/2004/02/skos/core#inScheme> <http://id.loc.gov/authorities#topicalTerms>.\n<http://id.loc.gov/authorities/sh85076767#concept> <http://www.w3.org/2004/02/skos/core#prefLabel> "Lichen planus"@en.\n<http://id.loc.gov/authorities/sh85076767#concept> <http://www.w3.org/2002/07/owl#sameAs> <info:lc/authorities/sh85076767>.\n<http://id.loc.gov/authorities/sh85076767#concept> <http://purl.org/dc/terms/modified> "1994-08-22T15:46:41-04:00"^^<http://www.w3.org/2001/XMLSchema#dateTime>.\n<http://id.loc.gov/authorities/sh85076767#concept> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2004/02/skos/core#Concept>.\n"
128
+
129
+ >> collection.to_ntriples
130
+
131
+ etc.
114
132
 
@@ -7,12 +7,34 @@ module RDFObject
7
7
  if predicate.could_be_a_safe_curie?
8
8
  predicate = Curie.parse predicate
9
9
  end
10
- self.find_all {|r|
10
+ matches = self.find_all {|r|
11
11
  if r[1][predicate]
12
12
  r[1]
13
13
  end
14
14
  }
15
+ resources = Collection.new
16
+ matches.each do | match |
17
+ resources[match[0]] = match[1]
18
+ end
19
+ return resources
15
20
  end
21
+
22
+ def find_by_predicate_and_object(predicate, object)
23
+ if predicate.could_be_a_safe_curie?
24
+ predicate = Curie.parse predicate
25
+ end
26
+ if object.could_be_a_safe_curie?
27
+ object = Curie.parse object
28
+ end
29
+ object = self[object] if self[object]
30
+ matches = self.find_all {|r| [*r[1][predicate]].index(object) }
31
+
32
+ resources = Collection.new
33
+ matches.each do | match |
34
+ resources[match[0]] = match[1]
35
+ end
36
+ return resources
37
+ end
16
38
 
17
39
  def find_or_create(uri)
18
40
  if uri.could_be_a_safe_curie?
@@ -32,5 +54,36 @@ module RDFObject
32
54
  parser.parse
33
55
  nil
34
56
  end
57
+
58
+ def to_ntriples
59
+ ntriples = ""
60
+ self.each_pair do | uri, resource |
61
+ ntriples << resource.to_ntriples
62
+ end
63
+ ntriples
64
+ end
65
+
66
+ def to_xml(depth=0)
67
+ namespaces = {}
68
+ rdf_data = ""
69
+ self.values.each do | resource |
70
+ ns, desc = resource.rdf_description_block(depth)
71
+ namespaces.merge!(ns)
72
+ rdf_data << desc
73
+ end
74
+ unless namespaces["xmlns:rdf"]
75
+ if x = namespaces.index("http://www.w3.org/1999/02/22-rdf-syntax-ns#")
76
+ namespaces.delete(x)
77
+ end
78
+ namespaces["xmlns:rdf"] = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
79
+ end
80
+
81
+ rdf = "<rdf:RDF"
82
+ namespaces.each_pair {|key, value| rdf << " #{key}=\"#{value}\""}
83
+ rdf <<">"
84
+ rdf << rdf_data
85
+ rdf << "</rdf:RDF>"
86
+ rdf
87
+ end
35
88
  end
36
89
  end
@@ -4,6 +4,7 @@ require 'curies'
4
4
 
5
5
  module RDFObject
6
6
  class Resource < OpenStruct
7
+ attr_reader :table
7
8
  def initialize(uri)
8
9
  if uri.could_be_a_safe_curie?
9
10
  uri = Curie.parse uri
@@ -101,6 +102,123 @@ module RDFObject
101
102
  end
102
103
  return true
103
104
  end
105
+
106
+ def to_ntriples
107
+ ntriples = ""
108
+ Curie.get_mappings.each do | prefix, uri |
109
+ if self[uri]
110
+ self[uri].keys.each do | pred |
111
+ if self[uri][pred].is_a?(Array)
112
+ objects = self[uri][pred]
113
+ else
114
+ objects = [self[uri][pred]]
115
+ end
116
+ objects.each do | object |
117
+ line = "<#{self.uri}> <#{uri}#{pred}> "
118
+ if (object.is_a?(Resource) or object.is_a?(ResourceReference))
119
+ line << "<#{object.uri}>"
120
+ else
121
+ line << "#{object.to_json}"
122
+ if (object.respond_to?(:data_type) || object.respond_to?(:language))
123
+ if object.data_type
124
+ line << "^^<#{object.data_type}>"
125
+ end
126
+ if object.language
127
+ line << "@#{object.language}"
128
+ end
129
+ end
130
+ end
131
+ line << ".\n"
132
+ ntriples << line
133
+ end
134
+ end
135
+ end
136
+ end
137
+ ntriples
138
+ end
139
+
140
+ def to_xml(depth=0)
141
+ namespaces, rdf_data = rdf_description_block(depth)
142
+ unless namespaces["xmlns:rdf"]
143
+ if x = namespaces.index("http://www.w3.org/1999/02/22-rdf-syntax-ns#")
144
+ namespaces.delete(x)
145
+ end
146
+ namespaces["xmlns:rdf"] = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
147
+ end
148
+
149
+ rdf = "<rdf:RDF"
150
+ namespaces.each_pair {|key, value| rdf << " #{key}=\"#{value}\""}
151
+ rdf <<">"
152
+ rdf << rdf_data
153
+ rdf << "</rdf:RDF>"
154
+ rdf
155
+ end
156
+
157
+ def rdf_description_block(depth)
158
+ rdf = "<rdf:Description rdf:about=\"#{CGI.escapeHTML(self.uri)}\">"
159
+ namespaces = {}
160
+ Curie.get_mappings.each_pair do |key, value|
161
+ if self.respond_to?(key.to_sym)
162
+ self.send(key.to_sym).each_pair do | predicate, objects |
163
+ [*objects].each do | object |
164
+ rdf << "<#{key}:#{predicate}"
165
+ namespaces["xmlns:#{key}"] = "#{Curie.parse("[#{key}:]")}"
166
+ if object.is_a?(RDFObject::ResourceReference)
167
+ if depth > 0
168
+ rdf << " rdf:resource=\"#{CGI.escapeHTML(object.uri)}\" />"
169
+ else
170
+ rdf << ">"
171
+ ns, rdf_data = object.resource.rdf_description_block(depth+1)
172
+ namespaces.merge!(ns)
173
+ rdf << rdf_data
174
+ rdf << "</#{key}:#{predicate}>"
175
+ end
176
+ else
177
+ if object.language
178
+ rdf << " xml:lang=\"#{object.language}\""
179
+ end
180
+ if object.data_type
181
+ rdf << " rdf:datatype=\"#{object.data_type}\""
182
+ end
183
+ rdf << ">#{CGI.escapeHTML(object.to_s)}</#{key}:#{predicate}>"
184
+ end
185
+ end
186
+ end
187
+ end
188
+ end
189
+ rdf << "</rdf:Description>"
190
+ [namespaces, rdf]
191
+ end
192
+
193
+ def ==(other)
194
+ return false unless self.uri == other.uri
195
+ Curie.get_mappings.each do | prefix, uri |
196
+ next unless self[uri] or other[uri]
197
+ return false if self[uri] && !other[uri]
198
+ return false if !self[uri] && other[uri]
199
+ return false if self[uri].class != other[uri].class
200
+ if self[uri] != other[uri]
201
+ if self[uri].is_a?(Hash)
202
+ return false unless self[uri].keys.eql?(other[uri].keys)
203
+ self[uri].keys.each do | pred |
204
+ if self[uri][pred].is_a?(Array)
205
+ return false unless self[uri][pred].length == other[uri][pred].length
206
+ else
207
+ if self[uri][pred].is_a?(Resource) or self[uri][pred].is_a?(ResourceReference)
208
+ return false unless other[uri][pred].is_a?(Resource) or other[uri][pred].is_a?(ResourceReference)
209
+ return false unless self.uri == other.uri
210
+ else
211
+ return false unless self[uri][pred] == other[uri][pred]
212
+ end
213
+ end
214
+ end
215
+ else
216
+ return false
217
+ end
218
+ end
219
+ end
220
+ true
221
+ end
104
222
  end
105
223
 
106
224
  class ResourceReference
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rdfobjects
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.6
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ross Singer
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-30 00:00:00 -04:00
12
+ date: 2009-11-10 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency