rdfobjects 0.6.6 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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