ro-bundle 0.1.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.
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