oa-graph 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1ee82d3a04f3b61c10ce562151dcdb0e72c90547
4
+ data.tar.gz: 70110ef9417988e88c8f3c301731767e218e4ced
5
+ SHA512:
6
+ metadata.gz: 7fb5b5f0cdab266514db38680df4016a46dcf9a35338f69a1db00a541ac2c43ad44106c33a6bd698076c68fc5e9baf5548170ea2ffe49b313e4ce2323db73965
7
+ data.tar.gz: 31470a60d945d2e04501d40b78c10163d6b0f615b0b70c8b202f72a7f25da533b57e1655c57bfbb32dcbac12114c9a2f7d5311b0ddc78a8c71f61f61c6a755d5
@@ -0,0 +1,31 @@
1
+ # Oa::Graph
2
+
3
+ A wrapper class for RDF::Graph that adds methods specific to OpenAnnotation graphs (See http://www.openannotation.org/spec/core/). Intended to be used for a single instance of an OpenAnnotation; adds methods specific to OpenAnnotation RDF::Graph objects.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'oa-graph'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle install
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install oa-graph
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/oa-graph/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
@@ -0,0 +1,44 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require "bundler/gem_tasks"
8
+
9
+ begin
10
+ require 'rspec/core/rake_task'
11
+ RSpec::Core::RakeTask.new(:spec)
12
+ rescue LoadError
13
+ end
14
+
15
+ task :default => :spec
16
+
17
+ desc "Generate RDoc with YARD"
18
+ task :doc => ['doc:generate']
19
+
20
+ namespace :doc do
21
+ begin
22
+ require 'yard'
23
+ require 'yard/rake/yardoc_task'
24
+
25
+ YARD::Rake::YardocTask.new(:generate) do |yt|
26
+ yt.files = Dir.glob(File.join('lib', '*.rb')) +
27
+ Dir.glob(File.join('lib', '**', '*.rb'))
28
+
29
+ yt.options = ['--output-dir', 'rdoc', '--readme', 'README.md',
30
+ '--files', 'LICENSE', '--protected', '--private', '--title',
31
+ 'OA::Graph', '--exclude', 'version.rb']
32
+ end
33
+ rescue LoadError
34
+ desc "Generate RDoc with YARD"
35
+ task :generate do
36
+ abort "Please install the YARD gem to generate rdoc."
37
+ end
38
+ end
39
+
40
+ desc "Remove generated documenation"
41
+ task :clean do
42
+ rm_r 'rdoc' if File.exists?('rdoc')
43
+ end
44
+ end
@@ -0,0 +1,191 @@
1
+ require 'oa/graph/version'
2
+ require 'linkeddata'
3
+
4
+ module OA
5
+ # a wrapper class for RDF::Graph that adds methods specific to OpenAnnotation
6
+ # (http://www.openannotation.org/spec/core/) Annotation objects. This is
7
+ # intended to be used for an RDF::Graph of a single annotation
8
+ class Graph
9
+
10
+ OA_CONTEXT_URL = 'http://www.w3.org/ns/oa.jsonld'
11
+ OA_DATED_CONTEXT_URL = 'http://www.w3.org/ns/oa-context-20130208.json'
12
+ IIIF_CONTEXT_URL = 'http://iiif.io/api/presentation/2/context.json'
13
+
14
+ # Class Methods ----------------------------------------------------------------
15
+
16
+ # given an RDF::Resource (an RDF::Node or RDF::URI), look for all the
17
+ # statements with that object as the subject, and recurse through the graph
18
+ # to find all descendant statements pertaining to the subject
19
+ # @param subject the RDF object to be used as the subject in the graph
20
+ # query. Should be an RDF::Node or RDF::URI
21
+ # @param [RDF::Graph] graph
22
+ # @return [Array[RDF::Statement]] all the triples with the given subject
23
+ def self.subject_statements(subject, graph)
24
+ result = []
25
+ graph.query([subject, nil, nil]).each { |stmt|
26
+ result << stmt
27
+ subject_statements(stmt.object, graph).each { |s| result << s }
28
+ }
29
+ result.uniq
30
+ end
31
+
32
+ # @return [RDF::Query] query for a subject :s with type of
33
+ # RDF::Vocab::OA.Annotation
34
+ def self.anno_query
35
+ q = RDF::Query.new
36
+ q << [:s, RDF.type, RDF::Vocab::OA.Annotation]
37
+ end
38
+
39
+ # Instance Methods -------------------------------------------------------------
40
+
41
+ # instantiate this class for an RDF::Graph of a single annotation
42
+ def initialize(rdf_graph)
43
+ @graph = rdf_graph
44
+ end
45
+
46
+ # @return json-ld representation of graph with OpenAnnotation context as a
47
+ # url
48
+ def jsonld_oa
49
+ inline_context = @graph.dump(:jsonld, context: OA_DATED_CONTEXT_URL)
50
+ hash_from_json = JSON.parse(inline_context)
51
+ hash_from_json['@context'] = OA_DATED_CONTEXT_URL
52
+ hash_from_json.to_json
53
+ end
54
+
55
+ # @return json-ld representation of graph with IIIF context as a url
56
+ def jsonld_iiif
57
+ inline_context = @graph.dump(:jsonld, context: IIIF_CONTEXT_URL)
58
+ hash_from_json = JSON.parse(inline_context)
59
+ hash_from_json['@context'] = IIIF_CONTEXT_URL
60
+ hash_from_json.to_json
61
+ end
62
+
63
+ # Canned Query methods -----------------------------------------------------
64
+
65
+ # @return [String] the id of this annotation as a url string, or nil if it
66
+ # is a Node
67
+ def id_as_url
68
+ solution = @graph.query self.class.anno_query
69
+ return if solution && solution.size == 1
70
+
71
+ rdf_resource = solution.first.s
72
+ rdf_resource.to_s if rdf_resource.is_a?(RDF::URI)
73
+ # TODO: raise exception if not a URI?
74
+ end
75
+
76
+ # @return [Array<String>] Array of urls expressing the OA motivated_by
77
+ # values
78
+ def motivated_by
79
+ motivations = []
80
+ q = self.class.anno_query.dup
81
+ q << [:s, RDF::Vocab::OA.motivatedBy, :motivated_by]
82
+ solution = @graph.query q
83
+ if solution && solution.size > 0
84
+ solution.each { |res|
85
+ motivations << res.motivated_by.to_s
86
+ }
87
+ end
88
+ # TODO: raise exception if none? (validation)
89
+ motivations
90
+ end
91
+
92
+ # @param [RDF::URI] predicate either RDF::Vocab::OA.hasTarget or RDF::Vocab::OA.hasBody
93
+ # @return [Array<String>] urls for the predicate, as an Array of Strings
94
+ def predicate_urls(predicate)
95
+ urls = []
96
+ predicate_solns = @graph.query [nil, predicate, nil]
97
+ predicate_solns.each { |predicate_stmt|
98
+ predicate_obj = predicate_stmt.object
99
+ urls << predicate_obj.to_str.strip if predicate_obj.is_a?(RDF::URI)
100
+ }
101
+ urls
102
+ end
103
+
104
+ # For all bodies that are of type ContentAsText, get the characters as a
105
+ # single String in the returned Array.
106
+ # @return [Array<String>] body chars as Strings, in an Array (one element
107
+ # for each contentAsText body)
108
+ def body_chars
109
+ result = []
110
+ q = RDF::Query.new
111
+ q << [nil, RDF::Vocab::OA.hasBody, :body]
112
+ q << [:body, RDF.type, RDF::Vocab::CNT.ContentAsText]
113
+ q << [:body, RDF::Vocab::CNT.chars, :body_chars]
114
+ solns = @graph.query q
115
+ solns.each { |soln|
116
+ result << soln.body_chars.value
117
+ }
118
+ result
119
+ end
120
+
121
+ # @return [String] The datetime from the annotatedAt property, or nil
122
+ def annotated_at
123
+ solution = @graph.query [nil, RDF::Vocab::OA.annotatedAt, nil]
124
+ return if solution && solution.size == 1
125
+
126
+ solution.first.object.to_s
127
+ end
128
+
129
+
130
+ # Changing the Graph -------------------------------------------------------
131
+
132
+ # remove all RDF::Vocab::OA.hasBody and .hasTarget statements
133
+ # and any other statements associated with body and target objects,
134
+ # leaving all statements to be stored as part of base object in LDP store
135
+ def remove_non_base_statements
136
+ remove_has_target_statements
137
+ remove_has_body_statements
138
+ end
139
+
140
+ # remove all RDF::Vocab::OA.hasBody statements and any other statements associated
141
+ # with body objects
142
+ def remove_has_body_statements
143
+ remove_predicate_and_its_object_statements RDF::Vocab::OA.hasBody
144
+ end
145
+
146
+ # remove all RDF::Vocab::OA.hasTarget statements and any other statements
147
+ # associated with body objects
148
+ def remove_has_target_statements
149
+ remove_predicate_and_its_object_statements RDF::Vocab::OA.hasTarget
150
+ end
151
+
152
+ # remove all such predicate statements and any other statements associated
153
+ # with predicates' objects
154
+ def remove_predicate_and_its_object_statements(predicate)
155
+ predicate_stmts = @graph.query([nil, predicate, nil])
156
+ predicate_stmts.each { |pstmt|
157
+ pred_obj = pstmt.object
158
+ OA::Graph.subject_statements(pred_obj, @graph).each { |s|
159
+ @graph.delete s
160
+ } unless !OA::Graph.subject_statements(pred_obj, @graph)
161
+ @graph.delete pstmt
162
+ }
163
+ end
164
+
165
+ # transform an outer blank node into a null relative URI
166
+ def make_null_relative_uri_out_of_blank_node
167
+ anno_stmts = @graph.query([nil, RDF.type, RDF::Vocab::OA.Annotation])
168
+ anno_rdf_obj = anno_stmts.first.subject
169
+ if anno_rdf_obj.is_a?(RDF::Node)
170
+ # use null relative URI representation of blank node
171
+ anno_subject = RDF::URI.new
172
+ else # it's already a URI
173
+ anno_subject = anno_rdf_obj
174
+ end
175
+ OA::Graph.subject_statements(anno_rdf_obj, @graph).each { |s|
176
+ if s.subject == anno_rdf_obj && anno_subject != anno_rdf_obj
177
+ @graph << RDF::Statement(subject: anno_subject,
178
+ predicate: s.predicate,
179
+ object: s.object)
180
+ @graph.delete s
181
+ end
182
+ }
183
+ end
184
+
185
+ # send unknown methods to RDF::Graph
186
+ def method_missing(sym, *args, &block)
187
+ @graph.send sym, *args, &block
188
+ end
189
+
190
+ end
191
+ end
@@ -0,0 +1,5 @@
1
+ module OA
2
+ class Graph
3
+ VERSION = '0.0.1'
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oa-graph
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Naomi Dushay
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: linkeddata
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: coveralls
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: yard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description:
112
+ email:
113
+ - ndushay@stanford.edu
114
+ - darren.weber@stanford.edu
115
+ executables: []
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - README.md
120
+ - Rakefile
121
+ - lib/oa/graph.rb
122
+ - lib/oa/graph/version.rb
123
+ homepage: https://github.com/sul-dlss/oa-graph
124
+ licenses:
125
+ - Apache-2.0
126
+ metadata: {}
127
+ post_install_message:
128
+ rdoc_options: []
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ requirements: []
142
+ rubyforge_project:
143
+ rubygems_version: 2.4.3
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: Wrapper class for RDF::Graph that adds methods specific to OpenAnnotation
147
+ graphs. http://www.openannotation.org/spec/core/
148
+ test_files: []
149
+ has_rdoc: