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.
- checksums.yaml +15 -0
- data/.gitignore +11 -0
- data/.ruby-env +1 -0
- data/.ruby-gemset +2 -0
- data/.ruby-version +2 -0
- data/.travis.yml +11 -0
- data/Changes.rdoc +129 -0
- data/Gemfile +11 -0
- data/Licence.rdoc +29 -0
- data/Rakefile +29 -0
- data/ReadMe.rdoc +57 -0
- data/bin/dir2ro +48 -0
- data/bin/ro-bundle-info +45 -0
- data/bin/verify-ro-bundle +27 -0
- data/bin/zip2ro +57 -0
- data/lib/ro-bundle.rb +45 -0
- data/lib/ro-bundle/exceptions.rb +30 -0
- data/lib/ro-bundle/file.rb +323 -0
- data/lib/ro-bundle/ro/agent.rb +73 -0
- data/lib/ro-bundle/ro/aggregate.rb +107 -0
- data/lib/ro-bundle/ro/annotation.rb +89 -0
- data/lib/ro-bundle/ro/directory.rb +120 -0
- data/lib/ro-bundle/ro/manifest.rb +338 -0
- data/lib/ro-bundle/ro/provenance.rb +153 -0
- data/lib/ro-bundle/util.rb +57 -0
- data/lib/ro-bundle/version.rb +13 -0
- data/ro-bundle.gemspec +43 -0
- data/test/data/HelloAnyone.robundle +0 -0
- data/test/data/empty-manifest.json +1 -0
- data/test/data/example3-manifest.json +40 -0
- data/test/data/invalid-manifest.json +5 -0
- data/test/data/invalid-manifest.robundle +0 -0
- data/test/helpers/fake_manifest.rb +23 -0
- data/test/helpers/fake_provenance.rb +32 -0
- data/test/helpers/list_tests.rb +22 -0
- data/test/tc_add_annotation.rb +571 -0
- data/test/tc_agent.rb +63 -0
- data/test/tc_aggregate.rb +116 -0
- data/test/tc_annotation.rb +84 -0
- data/test/tc_create.rb +170 -0
- data/test/tc_manifest.rb +221 -0
- data/test/tc_provenance.rb +121 -0
- data/test/tc_read.rb +66 -0
- data/test/tc_remove.rb +140 -0
- data/test/tc_util.rb +64 -0
- data/test/ts_ro_bundle.rb +28 -0
- 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
|
+
}
|
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
|