ro-bundle 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +11 -0
  3. data/.ruby-env +1 -0
  4. data/.ruby-gemset +2 -0
  5. data/.ruby-version +2 -0
  6. data/.travis.yml +11 -0
  7. data/Changes.rdoc +129 -0
  8. data/Gemfile +11 -0
  9. data/Licence.rdoc +29 -0
  10. data/Rakefile +29 -0
  11. data/ReadMe.rdoc +57 -0
  12. data/bin/dir2ro +48 -0
  13. data/bin/ro-bundle-info +45 -0
  14. data/bin/verify-ro-bundle +27 -0
  15. data/bin/zip2ro +57 -0
  16. data/lib/ro-bundle.rb +45 -0
  17. data/lib/ro-bundle/exceptions.rb +30 -0
  18. data/lib/ro-bundle/file.rb +323 -0
  19. data/lib/ro-bundle/ro/agent.rb +73 -0
  20. data/lib/ro-bundle/ro/aggregate.rb +107 -0
  21. data/lib/ro-bundle/ro/annotation.rb +89 -0
  22. data/lib/ro-bundle/ro/directory.rb +120 -0
  23. data/lib/ro-bundle/ro/manifest.rb +338 -0
  24. data/lib/ro-bundle/ro/provenance.rb +153 -0
  25. data/lib/ro-bundle/util.rb +57 -0
  26. data/lib/ro-bundle/version.rb +13 -0
  27. data/ro-bundle.gemspec +43 -0
  28. data/test/data/HelloAnyone.robundle +0 -0
  29. data/test/data/empty-manifest.json +1 -0
  30. data/test/data/example3-manifest.json +40 -0
  31. data/test/data/invalid-manifest.json +5 -0
  32. data/test/data/invalid-manifest.robundle +0 -0
  33. data/test/helpers/fake_manifest.rb +23 -0
  34. data/test/helpers/fake_provenance.rb +32 -0
  35. data/test/helpers/list_tests.rb +22 -0
  36. data/test/tc_add_annotation.rb +571 -0
  37. data/test/tc_agent.rb +63 -0
  38. data/test/tc_aggregate.rb +116 -0
  39. data/test/tc_annotation.rb +84 -0
  40. data/test/tc_create.rb +170 -0
  41. data/test/tc_manifest.rb +221 -0
  42. data/test/tc_provenance.rb +121 -0
  43. data/test/tc_read.rb +66 -0
  44. data/test/tc_remove.rb +140 -0
  45. data/test/tc_util.rb +64 -0
  46. data/test/ts_ro_bundle.rb +28 -0
  47. metadata +217 -0
@@ -0,0 +1,153 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2014 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Author: Robert Haines
7
+ #------------------------------------------------------------------------------
8
+
9
+ #
10
+ module ROBundle
11
+
12
+ # This module is a mixin for Research Object
13
+ # {provenance}[http://wf4ever.github.io/ro/bundle/draft/#provenance]
14
+ # information.
15
+ #
16
+ # To use this module simply provide an (optionally private) method named
17
+ # 'structure' which returns the internal fields of the object as a Hash.
18
+ #
19
+ # Fields added by this mixin are:
20
+ # * <tt>:authoredBy</tt>
21
+ # * <tt>:authoredOn</tt>
22
+ # * <tt>:createdBy</tt>
23
+ # * <tt>:createdOn</tt>
24
+ module Provenance
25
+
26
+ # :call-seq:
27
+ # add_author(author) -> Agent
28
+ #
29
+ # Add an author to the list of authors for this Research Object. The
30
+ # supplied parameter can either be an Agent or the name of an author as a
31
+ # String.
32
+ #
33
+ # The Agent object added to the Research Object is returned.
34
+ def add_author(author)
35
+ unless author.is_a?(Agent)
36
+ author = Agent.new(author.to_s)
37
+ end
38
+
39
+ @edited = true
40
+ (structure[:authoredBy] ||= []) << author
41
+ author
42
+ end
43
+
44
+ # :call-seq:
45
+ # authored_by -> Agents
46
+ #
47
+ # Return the list of Agents that authored this Research Object.
48
+ def authored_by
49
+ structure.fetch(:authoredBy, []).dup
50
+ end
51
+
52
+ # :call-seq:
53
+ # authored_on -> Time
54
+ #
55
+ # Return the time that this RO Bundle was edited as a Time object, or
56
+ # +nil+ if not present in the manifest.
57
+ def authored_on
58
+ Util.parse_time(structure[:authoredOn])
59
+ end
60
+
61
+ # :call-seq:
62
+ # authored_on = new_time
63
+ #
64
+ # Set a new authoredOn time for this Manifest. Anything that Ruby can
65
+ # interpret as a time is accepted and converted to ISO8601 format on
66
+ # serialization.
67
+ def authored_on=(new_time)
68
+ @edited = true
69
+ set_time(:authoredOn, new_time)
70
+ end
71
+
72
+ # :call-seq:
73
+ # created_by -> Agent
74
+ #
75
+ # Return the Agent that created this Research Object.
76
+ def created_by
77
+ structure[:createdBy]
78
+ end
79
+
80
+ # :call-seq:
81
+ # created_by = new_creator
82
+ #
83
+ # Set the Agent that has created this RO Bundle. Anything passed to this
84
+ # method that is not an Agent will be converted to an Agent before setting
85
+ # the value.
86
+ def created_by=(new_creator)
87
+ unless new_creator.instance_of?(Agent)
88
+ new_creator = Agent.new(new_creator.to_s)
89
+ end
90
+
91
+ @edited = true
92
+ structure[:createdBy] = new_creator
93
+ end
94
+
95
+ # :call-seq:
96
+ # created_on -> Time
97
+ #
98
+ # Return the time that this RO Bundle was created as a Time object, or
99
+ # +nil+ if not present in the manifest.
100
+ def created_on
101
+ Util.parse_time(structure[:createdOn])
102
+ end
103
+
104
+ # :call-seq:
105
+ # created_on = new_time
106
+ #
107
+ # Set a new createdOn time for this Manifest. Anything that Ruby can
108
+ # interpret as a time is accepted and converted to ISO8601 format on
109
+ # serialization.
110
+ def created_on=(new_time)
111
+ @edited = true
112
+ set_time(:createdOn, new_time)
113
+ end
114
+
115
+ # :call-seq:
116
+ # remove_author(name)
117
+ # remove_author(Agent)
118
+ #
119
+ # Remove the specified author or all authors with the specified name from
120
+ # the +authoredBy+ field.
121
+ def remove_author(object)
122
+ if object.is_a?(Agent)
123
+ structure[:authoredBy].delete(object)
124
+ @edited = true
125
+ else
126
+ changed = structure[:authoredBy].reject! { |a| a.name == object }
127
+ @edited = true unless changed.nil?
128
+ end
129
+ end
130
+
131
+ private
132
+
133
+ def init_provenance_defaults(struct)
134
+ creator = struct[:createdBy]
135
+ struct[:createdBy] = Agent.new(creator) unless creator.nil?
136
+ struct[:authoredBy] = [*struct.fetch(:authoredBy, [])].map do |agent|
137
+ Agent.new(agent)
138
+ end
139
+
140
+ struct
141
+ end
142
+
143
+ def set_time(key, time)
144
+ if time.instance_of?(String)
145
+ time = Time.parse(time)
146
+ end
147
+
148
+ structure[key] = time.iso8601
149
+ end
150
+
151
+ end
152
+
153
+ end
@@ -0,0 +1,57 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2014 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Author: Robert Haines
7
+ #------------------------------------------------------------------------------
8
+
9
+ #
10
+ module ROBundle
11
+
12
+ # A module with lots of utility functions.
13
+ module Util
14
+
15
+ # :call-seq:
16
+ # clean_json(json_hash) -> Hash
17
+ #
18
+ # Remove empty strings and nils from a json hash structure.
19
+ def self.clean_json(structure)
20
+ structure.delete_if do |_, v|
21
+ v.nil? || (v.respond_to?(:empty?) && v.empty?)
22
+ end
23
+ end
24
+
25
+ # :call-seq:
26
+ # parse_time(time) -> Time
27
+ #
28
+ # Parse a time string into a Time object. Does not try to parse +nil+.
29
+ def self.parse_time(time)
30
+ return if time.nil?
31
+ Time.parse(time)
32
+ end
33
+
34
+ # :call-seq:
35
+ # is_absolute_uri?(uri) -> true or false
36
+ #
37
+ # Is the supplied URI absolute? An absolute URI is a valid URI that starts
38
+ # with a scheme, such as http, https or urn.
39
+ def self.is_absolute_uri?(uri)
40
+ uri = URI.parse(uri) unless uri.is_a?(URI)
41
+ !uri.scheme.nil?
42
+ rescue URI::InvalidURIError
43
+ false
44
+ end
45
+
46
+ # :call-seq:
47
+ # strip_leading_slash(string)
48
+ #
49
+ # Return the supplied string with a leading slash removed.
50
+ def self.strip_leading_slash(string)
51
+ return if string.nil?
52
+ string.sub(/^\//, "")
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,13 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2014 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Author: Robert Haines
7
+ #------------------------------------------------------------------------------
8
+
9
+ #
10
+ module ROBundle
11
+ # The version number of this library as a String.
12
+ VERSION = "0.1.0"
13
+ end
data/ro-bundle.gemspec ADDED
@@ -0,0 +1,43 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2014 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Author: Robert Haines
7
+ #------------------------------------------------------------------------------
8
+
9
+ lib = File.expand_path('../lib', __FILE__)
10
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
11
+ require 'ro-bundle/version'
12
+
13
+ Gem::Specification.new do |spec|
14
+ spec.name = "ro-bundle"
15
+ spec.version = ROBundle::VERSION
16
+ spec.authors = ["Robert Haines"]
17
+ spec.email = ["support@mygrid.org.uk"]
18
+ spec.summary = "This library provides an API for manipulating "\
19
+ "Research Object (RO) bundles."
20
+ spec.description = "This library provides an API for manipulating "\
21
+ "Research Object (RO) bundles. The RO bundle specification can be found "\
22
+ "at http://purl.org/wf4ever/ro-bundle."
23
+ spec.homepage = "http://www.taverna.org.uk"
24
+ spec.license = "BSD"
25
+
26
+ spec.files = `git ls-files`.split($/)
27
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
28
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
29
+ spec.require_paths = ["lib"]
30
+
31
+ spec.has_rdoc = true
32
+ spec.extra_rdoc_files = [ "Changes.rdoc", "Licence.rdoc", "ReadMe.rdoc" ]
33
+ spec.rdoc_options = [ "-N", "--tab-width=2", "--main=ReadMe.rdoc" ]
34
+
35
+ spec.required_ruby_version = ">= 1.9.3"
36
+ spec.add_development_dependency "bundler", "~> 1.5"
37
+ spec.add_development_dependency "rake", "~> 10.1"
38
+ spec.add_development_dependency("rdoc", "~> 4.1")
39
+ spec.add_development_dependency "coveralls"
40
+ spec.add_runtime_dependency "ucf", "~> 1.0"
41
+ spec.add_runtime_dependency "json", "~> 1.8"
42
+ spec.add_runtime_dependency "uuid", "~> 2.3"
43
+ end
Binary file
@@ -0,0 +1 @@
1
+ {}
@@ -0,0 +1,40 @@
1
+ {
2
+ "@context": [
3
+ "https://w3id.org/bundle/context"
4
+ ],
5
+ "id": "/",
6
+ "manifest": "manifest.json",
7
+ "createdOn": "2013-03-05T17:29:03Z",
8
+ "createdBy": {
9
+ "uri": "http://example.com/foaf#alice",
10
+ "orcid": "http://orcid.org/0000-0002-1825-0097",
11
+ "name": "Alice W. Land" },
12
+ "history": "evolution.ttl",
13
+ "aggregates": [
14
+ { "file": "/folder/soup.jpeg" },
15
+ { "uri": "http://example.com/blog/" },
16
+ { "file": "/README.txt",
17
+ "mediatype": "text/plain",
18
+ "createdBy": {
19
+ "uri": "http://example.com/foaf#bob",
20
+ "name": "Bob Builder" },
21
+ "createdOn": "2013-02-12T19:37:32.939Z" },
22
+ { "uri": "http://example.com/comments.txt",
23
+ "bundledAs": {
24
+ "uri": "urn:uuid:a0cf8616-bee4-4a71-b21e-c60e6499a644",
25
+ "folder": "/folder/",
26
+ "filename": "external.txt" }
27
+ }
28
+ ],
29
+ "annotations": [
30
+ { "annotation": "urn:uuid:d67466b4-3aeb-4855-8203-90febe71abdf",
31
+ "about": "/folder/soup.jpeg",
32
+ "content": "annotations/soup-properties.ttl" },
33
+
34
+ { "about": "urn:uuid:a0cf8616-bee4-4a71-b21e-c60e6499a644",
35
+ "content": "http://example.com/blog/they-aggregated-our-file" },
36
+
37
+ { "about": "urn:uuid:d67466b4-3aeb-4855-8203-90febe71abdf",
38
+ "content": "annotations/a-meta-annotation-in-this-ro.txt" }
39
+ ]
40
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "@context": [
3
+ "https://w3id.org/bundle/context"
4
+ ],
5
+ "id": "/",
Binary file
@@ -0,0 +1,23 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2014 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Author: Robert Haines
7
+ #------------------------------------------------------------------------------
8
+
9
+ # Fake up a manifest for easy testing.
10
+ class FakeManifest < ROBundle::Manifest
11
+
12
+ def initialize(file)
13
+ @file = file
14
+ super()
15
+ end
16
+
17
+ private
18
+
19
+ def contents
20
+ File.read(@file)
21
+ end
22
+
23
+ end
@@ -0,0 +1,32 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2014 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Author: Robert Haines
7
+ #------------------------------------------------------------------------------
8
+
9
+ # Fake up a mixed in provenance module for easy testing.
10
+ class FakeProvenance
11
+ include ROBundle::Provenance
12
+
13
+ def initialize
14
+ @edited = false
15
+ end
16
+
17
+ def edited?
18
+ @edited
19
+ end
20
+
21
+ private
22
+
23
+ # This structure purposefully has no :authoredBy or :authoredOn fields.
24
+ def structure
25
+ @structure ||= init_provenance_defaults(
26
+ {
27
+ :createdBy => { :name => "Robert Haines" },
28
+ :createdOn => "2014-08-20T11:30:00+01:00"
29
+ }
30
+ )
31
+ end
32
+ end
@@ -0,0 +1,22 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2014 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Author: Robert Haines
7
+ #------------------------------------------------------------------------------
8
+
9
+ # Is the given file name in the list of history objects
10
+ def entry_in_history_list(entry, list)
11
+ name = entry.start_with?(".ro/") ? entry.sub(".ro/", "") : "/#{entry}"
12
+ list.include?(name)
13
+ end
14
+
15
+ # Is the given name in the list of agent objects
16
+ def name_in_agent_list(name, list)
17
+ list.each do |e|
18
+ return true if e.name == name
19
+ end
20
+
21
+ false
22
+ end
@@ -0,0 +1,571 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2014 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Author: Robert Haines
7
+ #------------------------------------------------------------------------------
8
+
9
+ require 'test/unit'
10
+ require "ro-bundle"
11
+
12
+ class TestAddAnnotation < Test::Unit::TestCase
13
+
14
+ def test_add_annotation_object
15
+ Dir.mktmpdir do |dir|
16
+ filename = File.join(dir, "test.bundle")
17
+
18
+ ro = "/"
19
+ uri = "http://www.example.com"
20
+ entry = "test_1.json"
21
+ annotation1 = ROBundle::Annotation.new(ro)
22
+ annotation2 = ROBundle::Annotation.new(entry, uri)
23
+ annotation3 = ROBundle::Annotation.new(annotation1)
24
+
25
+ ROBundle::File.create(filename) do |b|
26
+ b.add_aggregate(entry, $man_ex3)
27
+
28
+ ann = b.add_annotation(annotation1)
29
+ b.add_annotation(annotation2)
30
+ b.add_annotation(annotation3)
31
+
32
+ assert_equal annotation1, ann
33
+
34
+ ann1, ann2, ann3 = b.annotations
35
+
36
+ assert b.annotation?(ann1.annotation_id)
37
+ assert_same annotation1, ann1
38
+
39
+ assert b.annotation?(ann2.annotation_id)
40
+ assert_same annotation2, ann2
41
+ assert_equal uri, ann2.content
42
+
43
+ assert b.annotation?(ann3.annotation_id)
44
+ assert_same annotation3, ann3
45
+ end
46
+
47
+ ROBundle::File.open(filename) do |b|
48
+ refute b.aggregates.empty?
49
+ refute b.annotations.empty?
50
+ refute b.commit_required?
51
+
52
+ ann1, ann2, ann3 = b.annotations
53
+
54
+ assert b.annotation?(ann1.annotation_id)
55
+ assert_not_same annotation1, ann1
56
+
57
+ assert b.annotation?(ann2.annotation_id)
58
+ assert_not_same annotation2, ann2
59
+ assert_equal uri, ann2.content
60
+
61
+ assert b.annotation?(ann3.annotation_id)
62
+ assert_not_same annotation3, ann3
63
+ end
64
+ end
65
+ end
66
+
67
+ def test_add_annotation_object_no_target
68
+ Dir.mktmpdir do |dir|
69
+ filename = File.join(dir, "test.bundle")
70
+
71
+ entry = "test.html"
72
+ annotation = ROBundle::Annotation.new(entry)
73
+
74
+ ROBundle::File.create(filename) do |b|
75
+ assert_raises(Errno::ENOENT) do
76
+ b.add_annotation(annotation)
77
+ end
78
+ end
79
+
80
+ ROBundle::File.open(filename) do |b|
81
+ assert b.aggregates.empty?
82
+ assert b.annotations.empty?
83
+ refute b.commit_required?
84
+ end
85
+ end
86
+ end
87
+
88
+ def test_add_annotation_no_target
89
+ Dir.mktmpdir do |dir|
90
+ filename = File.join(dir, "test.bundle")
91
+
92
+ entry = "test.html"
93
+
94
+ ROBundle::File.create(filename) do |b|
95
+ assert_raises(Errno::ENOENT) do
96
+ b.add_annotation(entry)
97
+ end
98
+ end
99
+
100
+ ROBundle::File.open(filename) do |b|
101
+ assert b.aggregates.empty?
102
+ assert b.annotations.empty?
103
+ refute b.commit_required?
104
+ end
105
+ end
106
+ end
107
+
108
+ def test_add_file_annotations_to_aggregate
109
+ Dir.mktmpdir do |dir|
110
+ filename = File.join(dir, "test.bundle")
111
+
112
+ entry = "test_1.json"
113
+ entry2 = "test_2.json"
114
+
115
+ ROBundle::File.create(filename) do |b|
116
+ b.add_aggregate(entry, $man_ex3)
117
+ b.add_aggregate(entry2, $man_ex3)
118
+
119
+ ann = b.add_annotation(entry, $man_ex3)
120
+ b.add_annotation(entry, $man_ex3, :aggregate => true)
121
+ b.add_annotation(entry, entry2)
122
+
123
+ assert ann.instance_of?(ROBundle::Annotation)
124
+
125
+ ann1, ann2, ann3 = b.annotations
126
+
127
+ assert b.annotation?(ann1.annotation_id)
128
+ refute b.aggregate?(ann1.content)
129
+
130
+ assert b.annotation?(ann2.annotation_id)
131
+ assert b.aggregate?(ann2.content)
132
+
133
+ assert b.annotation?(ann3)
134
+ assert b.aggregate?(ann3.content)
135
+ end
136
+
137
+ ROBundle::File.open(filename) do |b|
138
+ refute b.aggregates.empty?
139
+ refute b.annotations.empty?
140
+ refute b.commit_required?
141
+
142
+ ann1, ann2, ann3 = b.annotations
143
+
144
+ assert b.annotation?(ann1.annotation_id)
145
+ refute b.aggregate?(ann1.content)
146
+
147
+ assert b.annotation?(ann2.annotation_id)
148
+ assert b.aggregate?(ann2.content)
149
+
150
+ assert b.annotation?(ann3)
151
+ assert b.aggregate?(ann3.content)
152
+ end
153
+ end
154
+ end
155
+
156
+ def test_add_uri_annotations_to_aggregate
157
+ Dir.mktmpdir do |dir|
158
+ filename = File.join(dir, "test.bundle")
159
+
160
+ entry = "test_1.json"
161
+ uri1 = "http://www.example.com/example1"
162
+ uri2 = URI.parse("http://www.example.com/example2")
163
+ uri3 = "http://www.example.com/example3"
164
+
165
+ ROBundle::File.create(filename) do |b|
166
+ b.add_aggregate(entry, $man_ex3)
167
+ b.add_aggregate(uri3)
168
+
169
+ ann = b.add_annotation(entry, uri1)
170
+ b.add_annotation(entry, uri2, :aggregate => true)
171
+ b.add_annotation(entry, uri3)
172
+
173
+ assert ann.instance_of?(ROBundle::Annotation)
174
+
175
+ ann1, ann2, ann3 = b.annotations
176
+
177
+ assert b.annotation?(ann1.annotation_id)
178
+ refute b.aggregate?(ann1.content)
179
+
180
+ assert b.annotation?(ann2.annotation_id)
181
+ assert b.aggregate?(ann2.content)
182
+
183
+ assert b.annotation?(ann3)
184
+ assert b.aggregate?(ann3.content)
185
+ end
186
+
187
+ ROBundle::File.open(filename) do |b|
188
+ refute b.aggregates.empty?
189
+ refute b.annotations.empty?
190
+ refute b.commit_required?
191
+
192
+ ann1, ann2, ann3 = b.annotations
193
+
194
+ assert b.annotation?(ann1.annotation_id)
195
+ refute b.aggregate?(ann1.content)
196
+
197
+ assert b.annotation?(ann2.annotation_id)
198
+ assert b.aggregate?(ann2.content)
199
+
200
+ assert b.annotation?(ann3)
201
+ assert b.aggregate?(ann3.content)
202
+ end
203
+ end
204
+ end
205
+
206
+ def test_add_content_annotations_to_aggregate
207
+ Dir.mktmpdir do |dir|
208
+ filename = File.join(dir, "test.bundle")
209
+
210
+ entry = "test_1.json"
211
+ uri = "http://www.example.com/example1"
212
+ content = File.read($man_ex3)
213
+
214
+ ROBundle::File.create(filename) do |b|
215
+ b.add_aggregate(entry, $man_ex3)
216
+ b.add_aggregate(uri)
217
+
218
+ ann = b.add_annotation(entry, content)
219
+ b.add_annotation(entry, content, :aggregate => true)
220
+ b.add_annotation(uri, content)
221
+
222
+ assert ann.instance_of?(ROBundle::Annotation)
223
+
224
+ ann1, ann2, ann3 = b.annotations
225
+
226
+ assert b.annotation?(ann1.annotation_id)
227
+ refute b.aggregate?(ann1.content)
228
+ assert_equal content, b.file.read(".ro/#{ann1.content}")
229
+
230
+ assert b.annotation?(ann2.annotation_id)
231
+ assert b.aggregate?(ann2.content)
232
+ assert_equal content, b.file.read(ann2.content)
233
+
234
+ assert b.annotation?(ann3)
235
+ refute b.aggregate?(ann3.content)
236
+ assert_equal content, b.file.read(".ro/#{ann3.content}")
237
+ end
238
+
239
+ ROBundle::File.open(filename) do |b|
240
+ refute b.aggregates.empty?
241
+ refute b.annotations.empty?
242
+ refute b.commit_required?
243
+
244
+ ann1, ann2, ann3 = b.annotations
245
+
246
+ assert b.annotation?(ann1.annotation_id)
247
+ refute b.aggregate?(ann1.content)
248
+ assert_equal content, b.file.read(".ro/#{ann1.content}")
249
+
250
+ assert b.annotation?(ann2.annotation_id)
251
+ assert b.aggregate?(ann2.content)
252
+ assert_equal content, b.file.read(ann2.content)
253
+
254
+ assert b.annotation?(ann3)
255
+ refute b.aggregate?(ann3.content)
256
+ assert_equal content, b.file.read(".ro/#{ann3.content}")
257
+ end
258
+ end
259
+ end
260
+
261
+ def test_add_file_annotations_to_uri
262
+ Dir.mktmpdir do |dir|
263
+ filename = File.join(dir, "test.bundle")
264
+
265
+ uri1 = "http://www.example.com/example1"
266
+ uri2 = URI.parse("http://www.example.com/example2")
267
+ entry1 = "test_1.json"
268
+ entry2 = "test_2.json"
269
+ entry3 = "test_3.json"
270
+
271
+ ROBundle::File.create(filename) do |b|
272
+ b.add_aggregate(uri2)
273
+ b.add_aggregate(entry3, $man_ex3)
274
+
275
+ ann = b.add_annotation(uri1, entry1)
276
+ b.add_annotation(uri1, entry2, :aggregate => true)
277
+ b.add_annotation(uri2, entry3)
278
+
279
+ assert ann.instance_of?(ROBundle::Annotation)
280
+
281
+ ann1, ann2, ann3 = b.annotations
282
+
283
+ assert b.annotation?(ann1.annotation_id)
284
+ refute b.aggregate?(ann1.content)
285
+
286
+ assert b.annotation?(ann2.annotation_id)
287
+ refute b.aggregate?(uri1)
288
+ assert b.aggregate?(ann2.content)
289
+
290
+ assert b.annotation?(ann3)
291
+ assert b.aggregate?(ann3.content)
292
+ end
293
+
294
+ ROBundle::File.open(filename) do |b|
295
+ refute b.aggregates.empty?
296
+ refute b.annotations.empty?
297
+ refute b.commit_required?
298
+
299
+ ann1, ann2, ann3 = b.annotations
300
+
301
+ assert b.annotation?(ann1.annotation_id)
302
+ refute b.aggregate?(ann1.content)
303
+
304
+ assert b.annotation?(ann2.annotation_id)
305
+ refute b.aggregate?(uri1)
306
+ assert b.aggregate?(ann2.content)
307
+
308
+ assert b.annotation?(ann3)
309
+ assert b.aggregate?(ann3.content)
310
+ end
311
+ end
312
+ end
313
+
314
+ def test_add_uri_annotations_to_uri
315
+ Dir.mktmpdir do |dir|
316
+ filename = File.join(dir, "test.bundle")
317
+
318
+ uri1 = "http://www.example.com/example1"
319
+ uri2 = URI.parse("http://www.example.com/example2")
320
+ uri3 = "http://www.example.com/example3"
321
+ uri4 = "http://www.example.com/example4"
322
+ uri5 = "http://www.example.com/example5"
323
+
324
+ ROBundle::File.create(filename) do |b|
325
+ b.add_aggregate(uri3)
326
+ b.add_aggregate(uri5)
327
+
328
+ ann = b.add_annotation(uri1, uri2)
329
+ b.add_annotation(uri1, uri4, :aggregate => true)
330
+ b.add_annotation(uri3, uri5)
331
+
332
+ assert ann.instance_of?(ROBundle::Annotation)
333
+
334
+ ann1, ann2, ann3 = b.annotations
335
+
336
+ assert b.annotation?(ann1.annotation_id)
337
+ refute b.aggregate?(ann1.content)
338
+
339
+ assert b.annotation?(ann2.annotation_id)
340
+ refute b.aggregate?(uri1)
341
+ assert b.aggregate?(ann2.content)
342
+
343
+ assert b.annotation?(ann3)
344
+ assert b.aggregate?(ann3.content)
345
+ end
346
+
347
+ ROBundle::File.open(filename) do |b|
348
+ refute b.aggregates.empty?
349
+ refute b.annotations.empty?
350
+ refute b.commit_required?
351
+
352
+ ann1, ann2, ann3 = b.annotations
353
+
354
+ assert b.annotation?(ann1.annotation_id)
355
+ refute b.aggregate?(ann1.content)
356
+
357
+ assert b.annotation?(ann2.annotation_id)
358
+ refute b.aggregate?(uri1)
359
+ assert b.aggregate?(ann2.content)
360
+
361
+ assert b.annotation?(ann3)
362
+ assert b.aggregate?(ann3.content)
363
+ end
364
+ end
365
+ end
366
+
367
+ def test_add_content_annotations_to_uri
368
+ Dir.mktmpdir do |dir|
369
+ filename = File.join(dir, "test.bundle")
370
+
371
+ uri1 = "http://www.example.com/example1"
372
+ uri2 = "http://www.example.com/example2"
373
+ content = File.read($man_ex3)
374
+
375
+ ROBundle::File.create(filename) do |b|
376
+ b.add_aggregate(uri2)
377
+
378
+ ann = b.add_annotation(uri1, content)
379
+ b.add_annotation(uri1, content, :aggregate => true)
380
+ b.add_annotation(uri2, content)
381
+
382
+ assert ann.instance_of?(ROBundle::Annotation)
383
+
384
+ ann1, ann2, ann3 = b.annotations
385
+
386
+ assert b.annotation?(ann1.annotation_id)
387
+ refute b.aggregate?(ann1.content)
388
+ assert_equal content, b.file.read(".ro/#{ann1.content}")
389
+
390
+ assert b.annotation?(ann2.annotation_id)
391
+ assert b.aggregate?(ann2.content)
392
+ assert_equal content, b.file.read(ann2.content)
393
+
394
+ assert b.annotation?(ann3)
395
+ refute b.aggregate?(ann3.content)
396
+ assert_equal content, b.file.read(".ro/#{ann3.content}")
397
+ end
398
+
399
+ ROBundle::File.open(filename) do |b|
400
+ refute b.aggregates.empty?
401
+ refute b.annotations.empty?
402
+ refute b.commit_required?
403
+
404
+ ann1, ann2, ann3 = b.annotations
405
+
406
+ assert b.annotation?(ann1.annotation_id)
407
+ refute b.aggregate?(ann1.content)
408
+ assert_equal content, b.file.read(".ro/#{ann1.content}")
409
+
410
+ assert b.annotation?(ann2.annotation_id)
411
+ assert b.aggregate?(ann2.content)
412
+ assert_equal content, b.file.read(ann2.content)
413
+
414
+ assert b.annotation?(ann3)
415
+ refute b.aggregate?(ann3.content)
416
+ assert_equal content, b.file.read(".ro/#{ann3.content}")
417
+ end
418
+ end
419
+ end
420
+
421
+ def test_add_file_annotations_to_annotation
422
+ Dir.mktmpdir do |dir|
423
+ filename = File.join(dir, "test.bundle")
424
+
425
+ ro = "/"
426
+ uri = "http://www.example.com"
427
+ annotation1 = ROBundle::Annotation.new(ro)
428
+ annotation2 = ROBundle::Annotation.new(ro, uri)
429
+ entry = "test_1.json"
430
+
431
+ ROBundle::File.create(filename) do |b|
432
+ b.add_aggregate(entry, $man_ex3)
433
+ b.add_annotation(annotation1)
434
+ b.add_annotation(annotation2)
435
+
436
+ ann = b.add_annotation(annotation1.annotation_id, $man_ex3)
437
+ b.add_annotation(annotation1, $man_ex3, :aggregate => true)
438
+ b.add_annotation(annotation2, entry)
439
+
440
+ assert ann.instance_of?(ROBundle::Annotation)
441
+
442
+ _, _, ann1, ann2, ann3 = b.annotations
443
+
444
+ assert b.annotation?(ann1.annotation_id)
445
+ refute b.aggregate?(ann1.content)
446
+
447
+ assert b.annotation?(ann2.annotation_id)
448
+ assert b.aggregate?(ann2.content)
449
+
450
+ assert b.annotation?(ann3)
451
+ assert b.aggregate?(ann3.content)
452
+ end
453
+
454
+ ROBundle::File.open(filename) do |b|
455
+ refute b.aggregates.empty?
456
+ refute b.annotations.empty?
457
+ refute b.commit_required?
458
+
459
+ _, _, ann1, ann2, ann3 = b.annotations
460
+
461
+ assert b.annotation?(ann1.annotation_id)
462
+ refute b.aggregate?(ann1.content)
463
+
464
+ assert b.annotation?(ann2.annotation_id)
465
+ assert b.aggregate?(ann2.content)
466
+
467
+ assert b.annotation?(ann3)
468
+ assert b.aggregate?(ann3.content)
469
+ end
470
+ end
471
+ end
472
+
473
+ def test_add_uri_annotations_to_annotation
474
+ Dir.mktmpdir do |dir|
475
+ filename = File.join(dir, "test.bundle")
476
+
477
+ ro = "/"
478
+ uri = "http://www.example.com"
479
+ annotation = ROBundle::Annotation.new(ro, uri)
480
+ uri1 = "http://www.example.com/example1"
481
+ uri2 = URI.parse("http://www.example.com/example2")
482
+ uri3 = "http://www.example.com/example3"
483
+
484
+ ROBundle::File.create(filename) do |b|
485
+ b.add_aggregate(uri3)
486
+ b.add_annotation(annotation)
487
+
488
+ ann = b.add_annotation(annotation, uri1)
489
+ b.add_annotation(annotation, uri2, :aggregate => true)
490
+ b.add_annotation(annotation, uri3)
491
+
492
+ assert ann.instance_of?(ROBundle::Annotation)
493
+
494
+ _, ann1, ann2, ann3 = b.annotations
495
+
496
+ assert b.annotation?(ann1.annotation_id)
497
+ refute b.aggregate?(ann1.content)
498
+
499
+ assert b.annotation?(ann2.annotation_id)
500
+ assert b.aggregate?(ann2.content)
501
+
502
+ assert b.annotation?(ann3)
503
+ assert b.aggregate?(ann3.content)
504
+ end
505
+
506
+ ROBundle::File.open(filename) do |b|
507
+ refute b.aggregates.empty?
508
+ refute b.annotations.empty?
509
+ refute b.commit_required?
510
+
511
+ _, ann1, ann2, ann3 = b.annotations
512
+
513
+ assert b.annotation?(ann1.annotation_id)
514
+ refute b.aggregate?(ann1.content)
515
+
516
+ assert b.annotation?(ann2.annotation_id)
517
+ assert b.aggregate?(ann2.content)
518
+
519
+ assert b.annotation?(ann3)
520
+ assert b.aggregate?(ann3.content)
521
+ end
522
+ end
523
+ end
524
+
525
+ def test_add_content_annotations_to_annotation
526
+ Dir.mktmpdir do |dir|
527
+ filename = File.join(dir, "test.bundle")
528
+
529
+ ro = "/"
530
+ uri = "http://www.example.com"
531
+ annotation = ROBundle::Annotation.new(ro, uri)
532
+ content = File.read($man_ex3)
533
+
534
+ ROBundle::File.create(filename) do |b|
535
+ b.add_annotation(annotation)
536
+
537
+ ann = b.add_annotation(annotation, content)
538
+ b.add_annotation(annotation, content, :aggregate => true)
539
+
540
+ assert ann.instance_of?(ROBundle::Annotation)
541
+
542
+ _, ann1, ann2 = b.annotations
543
+
544
+ assert b.annotation?(ann1.annotation_id)
545
+ refute b.aggregate?(ann1.content)
546
+ assert_equal content, b.file.read(".ro/#{ann1.content}")
547
+
548
+ assert b.annotation?(ann2.annotation_id)
549
+ assert b.aggregate?(ann2.content)
550
+ assert_equal content, b.file.read(ann2.content)
551
+ end
552
+
553
+ ROBundle::File.open(filename) do |b|
554
+ refute b.aggregates.empty?
555
+ refute b.annotations.empty?
556
+ refute b.commit_required?
557
+
558
+ _, ann1, ann2 = b.annotations
559
+
560
+ assert b.annotation?(ann1.annotation_id)
561
+ refute b.aggregate?(ann1.content)
562
+ assert_equal content, b.file.read(".ro/#{ann1.content}")
563
+
564
+ assert b.annotation?(ann2.annotation_id)
565
+ assert b.aggregate?(ann2.content)
566
+ assert_equal content, b.file.read(ann2.content)
567
+ end
568
+ end
569
+ end
570
+
571
+ end