ruby-avm-library 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +5 -0
- data/.gitignore +5 -0
- data/.rspec +5 -0
- data/Gemfile +14 -0
- data/README.md +56 -0
- data/Rakefile +2 -0
- data/autotest/discover.rb +2 -0
- data/bin/avm2avm +7 -0
- data/lib/avm/cli.rb +18 -0
- data/lib/avm/contact.rb +40 -0
- data/lib/avm/controlled_vocabulary.rb +23 -0
- data/lib/avm/coordinate_frame.rb +10 -0
- data/lib/avm/coordinate_system_projection.rb +10 -0
- data/lib/avm/creator.rb +123 -0
- data/lib/avm/image.rb +355 -0
- data/lib/avm/image_quality.rb +10 -0
- data/lib/avm/image_type.rb +10 -0
- data/lib/avm/node.rb +28 -0
- data/lib/avm/observation.rb +76 -0
- data/lib/avm/spatial_quality.rb +10 -0
- data/lib/avm/xmp.rb +157 -0
- data/lib/ruby-avm-library.rb +7 -0
- data/lib/ruby-avm-library/version.rb +7 -0
- data/reek.watchr +12 -0
- data/ruby-avm-library.gemspec +27 -0
- data/spec/avm/cli_spec.rb +0 -0
- data/spec/avm/contact_spec.rb +93 -0
- data/spec/avm/creator_spec.rb +268 -0
- data/spec/avm/image_spec.rb +350 -0
- data/spec/avm/observation_spec.rb +191 -0
- data/spec/avm/xmp_spec.rb +154 -0
- data/spec/quick_fix_formatter.rb +26 -0
- data/spec/sample_files/creator/no_creator.xmp +14 -0
- data/spec/sample_files/creator/one_creator.xmp +28 -0
- data/spec/sample_files/creator/two_creators.xmp +26 -0
- data/spec/sample_files/image/both.xmp +101 -0
- data/spec/sample_files/image/light_years.xmp +96 -0
- data/spec/sample_files/image/nothing.xmp +18 -0
- data/spec/sample_files/image/redshift.xmp +101 -0
- data/spec/sample_files/image/single_value_light_years.xmp +96 -0
- data/spec/sample_files/observation/none.xmp +5 -0
- data/spec/sample_files/observation/one.xmp +17 -0
- data/spec/sample_files/observation/two.xmp +17 -0
- data/spec/spec_helper.rb +3 -0
- metadata +184 -0
@@ -0,0 +1,268 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'avm/image'
|
3
|
+
require 'avm/creator'
|
4
|
+
|
5
|
+
describe AVM::Creator do
|
6
|
+
let(:image) { AVM::Image.new }
|
7
|
+
let(:creator) { image.creator }
|
8
|
+
|
9
|
+
let(:name) { 'Space Telescope Science Institute' }
|
10
|
+
let(:url) { 'http://www.stsci.edu/' }
|
11
|
+
let(:rights) { 'Public Domain' }
|
12
|
+
|
13
|
+
subject { creator }
|
14
|
+
|
15
|
+
def self.can_read_properties
|
16
|
+
its(:name) { should == name }
|
17
|
+
its(:url) { should == url }
|
18
|
+
its(:rights) { should == rights }
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#merge!' do
|
22
|
+
before { creator.merge!(:name => name, :url => url, :rights => rights) }
|
23
|
+
|
24
|
+
can_read_properties
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'setters' do
|
28
|
+
before {
|
29
|
+
creator.name = name
|
30
|
+
creator.url = url
|
31
|
+
creator.rights = rights
|
32
|
+
}
|
33
|
+
|
34
|
+
can_read_properties
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'primary contact passthrough' do
|
38
|
+
context 'no contacts' do
|
39
|
+
its(:address) { should be_nil }
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'one contact, must be primary' do
|
43
|
+
let(:first_contact) { AVM::Contact.new(
|
44
|
+
:name => 'zz bill',
|
45
|
+
:address => first_contact_address,
|
46
|
+
:city => first_contact_address,
|
47
|
+
:state => first_contact_address,
|
48
|
+
:postal_code => first_contact_address,
|
49
|
+
:country => first_contact_address
|
50
|
+
) }
|
51
|
+
let(:first_contact_address) { 'first contact' }
|
52
|
+
|
53
|
+
before { creator.contacts << first_contact }
|
54
|
+
|
55
|
+
fields = [ :address, :city, :state, :province, :postal_code, :zip, :country ]
|
56
|
+
fields.each { |field| its(field) { should == first_contact_address } }
|
57
|
+
|
58
|
+
specify { creator.to_a.should == [
|
59
|
+
first_contact.to_h
|
60
|
+
] }
|
61
|
+
|
62
|
+
context 'two contacts' do
|
63
|
+
let(:second_contact) { AVM::Contact.new(
|
64
|
+
:name => 'aa bill',
|
65
|
+
:address => second_contact_address,
|
66
|
+
:city => second_contact_address,
|
67
|
+
:state => second_contact_address,
|
68
|
+
:postal_code => second_contact_address,
|
69
|
+
:country => second_contact_address
|
70
|
+
) }
|
71
|
+
let(:second_contact_address) { 'second contact' }
|
72
|
+
|
73
|
+
before { creator.contacts << second_contact }
|
74
|
+
|
75
|
+
context 'no primary, first alphabetical is primary' do
|
76
|
+
subject { second_contact }
|
77
|
+
|
78
|
+
fields.each { |field| its(field) { should == second_contact_address } }
|
79
|
+
|
80
|
+
specify { creator.to_a.should == [
|
81
|
+
second_contact.to_h, first_contact.to_h
|
82
|
+
] }
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'one is primary, use it' do
|
86
|
+
before { first_contact.primary = true }
|
87
|
+
|
88
|
+
fields.each { |field| its(field) { should == first_contact_address } }
|
89
|
+
|
90
|
+
specify { creator.to_a.should == [
|
91
|
+
first_contact.to_h, second_contact.to_h
|
92
|
+
] }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '#create_contact' do
|
99
|
+
let(:first_name) { 'John' }
|
100
|
+
let(:first_contact) { creator.create_contact(:name => first_name) }
|
101
|
+
|
102
|
+
subject { creator.primary_contact }
|
103
|
+
before { first_contact }
|
104
|
+
|
105
|
+
its(:name) { should == first_name }
|
106
|
+
end
|
107
|
+
|
108
|
+
describe '#from_xml' do
|
109
|
+
let(:document) { image.to_xml }
|
110
|
+
let(:image) { AVM::Image.from_xml(File.read(file_path)) }
|
111
|
+
|
112
|
+
subject { image }
|
113
|
+
|
114
|
+
context 'no creator' do
|
115
|
+
let(:file_path) { 'spec/sample_files/creator/no_creator.xmp' }
|
116
|
+
|
117
|
+
its('creator.length') { should == 0 }
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'one creator' do
|
121
|
+
let(:file_path) { 'spec/sample_files/creator/one_creator.xmp' }
|
122
|
+
|
123
|
+
its('creator.length') { should == 1 }
|
124
|
+
|
125
|
+
def self.field_checks
|
126
|
+
its(:name) { should == name }
|
127
|
+
its(:address) { should == address }
|
128
|
+
its(:city) { should == city }
|
129
|
+
its(:state) { should == state }
|
130
|
+
its(:zip) { should == zip }
|
131
|
+
its(:country) { should == country }
|
132
|
+
its(:email) { should == email }
|
133
|
+
its(:telephone) { should == telephone }
|
134
|
+
end
|
135
|
+
|
136
|
+
let(:name) { 'John Bintz' }
|
137
|
+
let(:email) { 'bintz@stsci.edu' }
|
138
|
+
let(:telephone) { '800-555-1234' }
|
139
|
+
let(:address) { '3700 San Martin Drive' }
|
140
|
+
let(:city) { 'Baltimore' }
|
141
|
+
let(:state) { 'Maryland' }
|
142
|
+
let(:zip) { '21218' }
|
143
|
+
let(:country) { 'USA' }
|
144
|
+
|
145
|
+
context 'creator one' do
|
146
|
+
subject { image.creator[0] }
|
147
|
+
|
148
|
+
field_checks
|
149
|
+
|
150
|
+
it { should be_primary }
|
151
|
+
end
|
152
|
+
|
153
|
+
context 'two creators' do
|
154
|
+
let(:file_path) { 'spec/sample_files/creator/two_creators.xmp' }
|
155
|
+
|
156
|
+
its('creator.length') { should == 2 }
|
157
|
+
|
158
|
+
context 'first creator' do
|
159
|
+
subject { image.creator[0] }
|
160
|
+
|
161
|
+
field_checks
|
162
|
+
|
163
|
+
it { should be_primary }
|
164
|
+
end
|
165
|
+
|
166
|
+
context 'second creator' do
|
167
|
+
subject { image.creator[1] }
|
168
|
+
|
169
|
+
field_checks
|
170
|
+
|
171
|
+
it { should_not be_primary }
|
172
|
+
|
173
|
+
let(:name) { 'Aohn Bintz' }
|
174
|
+
let(:email) { 'aohn@stsci.edu' }
|
175
|
+
let(:telephone) { '800-555-2345' }
|
176
|
+
let(:address) { '3700 San Martin Drive' }
|
177
|
+
let(:city) { 'Baltimore' }
|
178
|
+
let(:state) { 'Maryland' }
|
179
|
+
let(:zip) { '21218' }
|
180
|
+
let(:country) { 'USA' }
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe 'contact name node' do
|
187
|
+
let(:first_name) { 'John' }
|
188
|
+
let(:second_name) { 'Zohn' }
|
189
|
+
|
190
|
+
let(:first_contact) { creator.create_contact(first_contact_options) }
|
191
|
+
let(:second_contact) { creator.create_contact(second_contact_options) }
|
192
|
+
|
193
|
+
let(:first_contact_options) { { :name => first_name } }
|
194
|
+
let(:second_contact_options) { { :name => second_name } }
|
195
|
+
|
196
|
+
subject { image.to_xml.search('//dc:creator/rdf:Seq/rdf:li').collect { |node| node.text } }
|
197
|
+
|
198
|
+
context 'no contacts' do
|
199
|
+
it { should == [] }
|
200
|
+
end
|
201
|
+
|
202
|
+
context 'one contact' do
|
203
|
+
before { first_contact }
|
204
|
+
|
205
|
+
it { should == [ first_name ] }
|
206
|
+
end
|
207
|
+
|
208
|
+
context 'second contact' do
|
209
|
+
before { second_contact ; first_contact }
|
210
|
+
|
211
|
+
it { should == [ first_name, second_name ] }
|
212
|
+
end
|
213
|
+
|
214
|
+
describe 'everything else uses primary' do
|
215
|
+
let(:fields) { [ :address, :city, :state, :zip, :country ] }
|
216
|
+
|
217
|
+
def other_fields(what)
|
218
|
+
Hash[fields.zip(Array.new(fields.length, what))]
|
219
|
+
end
|
220
|
+
|
221
|
+
let(:first_contact_options) { { :name => first_name }.merge(other_fields('one')) }
|
222
|
+
let(:second_contact_options) { { :name => second_name }.merge(other_fields('two')) }
|
223
|
+
|
224
|
+
before { second_contact ; first_contact }
|
225
|
+
|
226
|
+
specify {
|
227
|
+
%w{CiAdrExtadr CiAdrCity CiAdrRegion CiAdrPcode CiAdrCtry}.each do |element_name|
|
228
|
+
image.to_xml.at_xpath("//Iptc4xmpCore:#{element_name}").text.should == 'one'
|
229
|
+
end
|
230
|
+
}
|
231
|
+
end
|
232
|
+
|
233
|
+
describe 'contact emails, telephones' do
|
234
|
+
let(:first_email) { 'bintz@stsci.edu' }
|
235
|
+
let(:second_email) { 'bintz-2@stsci.edu' }
|
236
|
+
|
237
|
+
let(:first_phone) { '123-456-7890' }
|
238
|
+
let(:second_phone) { '234-567-8901' }
|
239
|
+
|
240
|
+
let(:first_contact_options) { { :name => first_name, :email => first_email, :telephone => first_phone } }
|
241
|
+
let(:second_contact_options) { { :name => second_name, :email => second_email, :telephone => second_phone } }
|
242
|
+
|
243
|
+
let(:contact_info) { image.to_xml.search('//Iptc4xmpCore:CreatorContactInfo') }
|
244
|
+
|
245
|
+
let(:telephone_text) { contact_info.at_xpath('./Iptc4xmpCore:CiTelWork').text }
|
246
|
+
let(:email_text) { contact_info.at_xpath('./Iptc4xmpCore:CiEmailWork').text }
|
247
|
+
|
248
|
+
context 'no contacts' do
|
249
|
+
specify { expect { telephone_text }.to raise_error }
|
250
|
+
specify { expect { email_text }.to raise_error }
|
251
|
+
end
|
252
|
+
|
253
|
+
context 'one contact' do
|
254
|
+
before { first_contact }
|
255
|
+
|
256
|
+
specify { telephone_text.should == first_phone }
|
257
|
+
specify { email_text.should == first_email }
|
258
|
+
end
|
259
|
+
|
260
|
+
context 'two contacts' do
|
261
|
+
before { first_contact ; second_contact }
|
262
|
+
|
263
|
+
specify { telephone_text.should == [ first_phone, second_phone ] * ',' }
|
264
|
+
specify { email_text.should == [ first_email, second_email ] * ',' }
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
@@ -0,0 +1,350 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'avm/image'
|
3
|
+
|
4
|
+
describe AVM::Image do
|
5
|
+
let(:image) { self.class.describes.new(options) }
|
6
|
+
let(:options) { {} }
|
7
|
+
|
8
|
+
subject { image }
|
9
|
+
|
10
|
+
let(:title) { 'My title' }
|
11
|
+
let(:headline) { 'Headline' }
|
12
|
+
let(:description) { 'Description' }
|
13
|
+
let(:distance_notes) { 'Distance Notes' }
|
14
|
+
let(:spectral_notes) { 'Spectral Notes' }
|
15
|
+
let(:reference_url) { 'Reference URL' }
|
16
|
+
let(:credit) { 'Credit' }
|
17
|
+
let(:date) { '2010-01-01' }
|
18
|
+
let(:id) { 'ID' }
|
19
|
+
let(:type) { 'Observation' }
|
20
|
+
let(:image_quality) { 'Good' }
|
21
|
+
let(:redshift) { 'Redshift' }
|
22
|
+
let(:light_years) { 'Light years' }
|
23
|
+
|
24
|
+
let(:subject_names) { [ 'Name one', 'Name two' ] }
|
25
|
+
let(:categories) { [ 'Category one', 'Category two' ] }
|
26
|
+
|
27
|
+
let(:coordinate_frame) { 'ICRS' }
|
28
|
+
let(:equinox) { '100' }
|
29
|
+
let(:reference_value) { [ 100, 50 ] }
|
30
|
+
let(:reference_dimension) { [ 200, 150 ] }
|
31
|
+
let(:reference_pixel) { [ 25, 15 ] }
|
32
|
+
let(:spatial_scale) { [ 40, 35 ] }
|
33
|
+
let(:spatial_rotation) { 10.0 }
|
34
|
+
let(:coordinate_system_projection) { 'TAN' }
|
35
|
+
let(:spatial_quality) { 'Full' }
|
36
|
+
let(:spatial_notes) { 'Spatial Notes' }
|
37
|
+
let(:fits_header) { 'FITS header' }
|
38
|
+
let(:spatial_cd_matrix) { [ 1, 2, 3, 4 ] }
|
39
|
+
|
40
|
+
let(:publisher) { 'Publisher' }
|
41
|
+
let(:publisher_id) { 'Publisher ID' }
|
42
|
+
let(:resource_id) { 'Resource ID' }
|
43
|
+
let(:resource_url) { 'Resource URL' }
|
44
|
+
let(:related_resources) { [ 'Resource 1', 'Resource 2' ] }
|
45
|
+
let(:metadata_date) { '2010-01-05' }
|
46
|
+
let(:metadata_version) { '1.2' }
|
47
|
+
|
48
|
+
def self.with_all_options
|
49
|
+
let(:options) { {
|
50
|
+
:title => title,
|
51
|
+
:headline => headline,
|
52
|
+
:description => description,
|
53
|
+
:distance_notes => distance_notes,
|
54
|
+
:spectral_notes => spectral_notes,
|
55
|
+
:reference_url => reference_url,
|
56
|
+
:credit => credit,
|
57
|
+
:date => date,
|
58
|
+
:id => id,
|
59
|
+
:type => type,
|
60
|
+
:quality => image_quality,
|
61
|
+
:redshift => redshift,
|
62
|
+
:light_years => light_years,
|
63
|
+
:coordinate_frame => coordinate_frame,
|
64
|
+
:equinox => equinox,
|
65
|
+
:reference_value => reference_value,
|
66
|
+
:reference_dimension => reference_dimension,
|
67
|
+
:reference_pixel => reference_pixel,
|
68
|
+
:spatial_scale => spatial_scale,
|
69
|
+
:spatial_rotation => spatial_rotation,
|
70
|
+
:coordinate_system_projection => coordinate_system_projection,
|
71
|
+
:spatial_quality => spatial_quality,
|
72
|
+
:spatial_notes => spatial_notes,
|
73
|
+
:fits_header => fits_header,
|
74
|
+
:spatial_cd_matrix => spatial_cd_matrix,
|
75
|
+
:publisher => publisher,
|
76
|
+
:publisher_id => publisher_id,
|
77
|
+
:resource_id => resource_id,
|
78
|
+
:resource_url => resource_url,
|
79
|
+
:related_resources => related_resources,
|
80
|
+
:metadata_date => metadata_date,
|
81
|
+
:metadata_version => metadata_version,
|
82
|
+
:subject_names => subject_names,
|
83
|
+
:categories => categories
|
84
|
+
} }
|
85
|
+
end
|
86
|
+
|
87
|
+
let(:avm_image_type) { eval("AVM::ImageType::#{type}") }
|
88
|
+
let(:avm_image_quality) { eval("AVM::ImageQuality::#{image_quality}") }
|
89
|
+
let(:avm_coordinate_frame) { eval("AVM::CoordinateFrame::#{coordinate_frame}") }
|
90
|
+
let(:avm_coordinate_system_projection) { eval("AVM::CoordinateSystemProjection::#{coordinate_system_projection}") }
|
91
|
+
let(:avm_spatial_quality) { eval("AVM::SpatialQuality::#{spatial_quality}") }
|
92
|
+
|
93
|
+
def self.has_most_options
|
94
|
+
its(:creator) { should be_a_kind_of(AVM::Creator) }
|
95
|
+
its(:title) { should == title }
|
96
|
+
its(:headline) { should == headline }
|
97
|
+
its(:description) { should == description }
|
98
|
+
its(:distance_notes) { should == distance_notes }
|
99
|
+
its(:spectral_notes) { should == spectral_notes }
|
100
|
+
its(:reference_url) { should == reference_url }
|
101
|
+
its(:credit) { should == credit }
|
102
|
+
its(:date) { should == Time.parse(date) }
|
103
|
+
its(:id) { should == id }
|
104
|
+
its(:image_type) { should be_a_kind_of avm_image_type }
|
105
|
+
its(:image_quality) { should be_a_kind_of avm_image_quality }
|
106
|
+
|
107
|
+
its(:coordinate_frame) { should be_a_kind_of avm_coordinate_frame }
|
108
|
+
its(:equinox) { should == equinox }
|
109
|
+
its(:reference_value) { should == reference_value }
|
110
|
+
its(:reference_dimension) { should == reference_dimension }
|
111
|
+
its(:reference_pixel) { should == reference_pixel }
|
112
|
+
its(:spatial_scale) { should == spatial_scale }
|
113
|
+
its(:spatial_rotation) { should == spatial_rotation }
|
114
|
+
its(:coordinate_system_projection) { should be_a_kind_of avm_coordinate_system_projection }
|
115
|
+
its(:spatial_quality) { should be_a_kind_of avm_spatial_quality }
|
116
|
+
its(:spatial_notes) { should == spatial_notes }
|
117
|
+
its(:fits_header) { should == fits_header }
|
118
|
+
its(:spatial_cd_matrix) { should == spatial_cd_matrix }
|
119
|
+
|
120
|
+
its(:publisher) { should == publisher }
|
121
|
+
its(:publisher_id) { should == publisher_id }
|
122
|
+
its(:resource_id) { should == resource_id }
|
123
|
+
its(:resource_url) { should == resource_url }
|
124
|
+
its(:related_resources) { should == related_resources }
|
125
|
+
its(:metadata_date) { should == Time.parse(metadata_date) }
|
126
|
+
its(:metadata_version) { should == metadata_version }
|
127
|
+
|
128
|
+
its(:subject_names) { should == subject_names }
|
129
|
+
its(:categories) { should == categories }
|
130
|
+
|
131
|
+
it { should be_valid }
|
132
|
+
end
|
133
|
+
|
134
|
+
describe '#initialize' do
|
135
|
+
with_all_options
|
136
|
+
|
137
|
+
it { should be_a_kind_of(AVM::Image) }
|
138
|
+
|
139
|
+
has_most_options
|
140
|
+
|
141
|
+
its(:to_h) { should == {
|
142
|
+
:title => title,
|
143
|
+
:headline => headline,
|
144
|
+
:description => description,
|
145
|
+
:distance_notes => distance_notes,
|
146
|
+
:spectral_notes => spectral_notes,
|
147
|
+
:reference_url => reference_url,
|
148
|
+
:credit => credit,
|
149
|
+
:date => Time.parse(date),
|
150
|
+
:id => id,
|
151
|
+
:image_type => avm_image_type.new,
|
152
|
+
:image_quality => avm_image_quality.new,
|
153
|
+
:coordinate_frame => avm_coordinate_frame.new,
|
154
|
+
:equinox => equinox,
|
155
|
+
:reference_value => reference_value,
|
156
|
+
:reference_dimension => reference_dimension,
|
157
|
+
:reference_pixel => reference_pixel,
|
158
|
+
:spatial_scale => spatial_scale,
|
159
|
+
:spatial_rotation => spatial_rotation,
|
160
|
+
:coordinate_system_projection => avm_coordinate_system_projection.new,
|
161
|
+
:spatial_quality => avm_spatial_quality.new,
|
162
|
+
:spatial_notes => spatial_notes,
|
163
|
+
:fits_header => fits_header,
|
164
|
+
:spatial_cd_matrix => spatial_cd_matrix,
|
165
|
+
:distance => [ light_years, redshift ],
|
166
|
+
:creator => [],
|
167
|
+
:publisher => publisher,
|
168
|
+
:publisher_id => publisher_id,
|
169
|
+
:resource_id => resource_id,
|
170
|
+
:resource_url => resource_url,
|
171
|
+
:related_resources => related_resources,
|
172
|
+
:metadata_date => Time.parse(metadata_date),
|
173
|
+
:metadata_version => metadata_version,
|
174
|
+
:subject_names => subject_names,
|
175
|
+
:categories => categories,
|
176
|
+
:observations => []
|
177
|
+
} }
|
178
|
+
|
179
|
+
its(:distance) { should == [ light_years, redshift ] }
|
180
|
+
end
|
181
|
+
|
182
|
+
describe 'not valid' do
|
183
|
+
let(:image) { AVM::Image.new }
|
184
|
+
|
185
|
+
it { should_not be_valid }
|
186
|
+
end
|
187
|
+
|
188
|
+
describe '.from_xml' do
|
189
|
+
let!(:image) { AVM::Image.from_xml(File.read(file_path)) }
|
190
|
+
|
191
|
+
subject { image }
|
192
|
+
|
193
|
+
context "nothing in it" do
|
194
|
+
let(:file_path) { 'spec/sample_files/image/nothing.xmp' }
|
195
|
+
|
196
|
+
[ :title, :headline, :description, :distance_notes,
|
197
|
+
:spectral_notes, :reference_url, :credit, :date,
|
198
|
+
:id, :image_type, :image_quality, :redshift,
|
199
|
+
:light_years, :coordinate_frame, :equinox, :reference_value,
|
200
|
+
:reference_dimension, :reference_pixel, :spatial_scale,
|
201
|
+
:spatial_rotation, :coordinate_system_projection, :spatial_quality, :spatial_notes,
|
202
|
+
:fits_header, :spatial_cd_matrix, :subject_names, :categories
|
203
|
+
].each do |field|
|
204
|
+
its(field) { should be_nil }
|
205
|
+
end
|
206
|
+
|
207
|
+
it { should_not be_valid }
|
208
|
+
end
|
209
|
+
|
210
|
+
context "image in it" do
|
211
|
+
context 'distance as a single value, assume light years' do
|
212
|
+
let(:file_path) { 'spec/sample_files/image/single_value_light_years.xmp' }
|
213
|
+
|
214
|
+
has_most_options
|
215
|
+
|
216
|
+
its(:redshift) { should be_nil }
|
217
|
+
its(:light_years) { should == light_years }
|
218
|
+
end
|
219
|
+
|
220
|
+
context "distance in light years" do
|
221
|
+
let(:file_path) { 'spec/sample_files/image/light_years.xmp' }
|
222
|
+
|
223
|
+
has_most_options
|
224
|
+
|
225
|
+
its(:redshift) { should be_nil }
|
226
|
+
its(:light_years) { should == light_years }
|
227
|
+
end
|
228
|
+
|
229
|
+
context "distaince in redshift" do
|
230
|
+
let(:file_path) { 'spec/sample_files/image/redshift.xmp' }
|
231
|
+
|
232
|
+
has_most_options
|
233
|
+
|
234
|
+
its(:light_years) { should be_nil }
|
235
|
+
its(:redshift) { should == redshift }
|
236
|
+
end
|
237
|
+
|
238
|
+
context "distance in both" do
|
239
|
+
let(:file_path) { 'spec/sample_files/image/both.xmp' }
|
240
|
+
|
241
|
+
has_most_options
|
242
|
+
|
243
|
+
its(:light_years) { should == light_years }
|
244
|
+
its(:redshift) { should == redshift }
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
describe '#to_xml' do
|
250
|
+
let(:xml) { image.to_xml }
|
251
|
+
|
252
|
+
let(:dublin_core) { xml.at_xpath('//rdf:Description[@rdf:about="Dublin Core"]') }
|
253
|
+
let(:photoshop) { xml.at_xpath('//rdf:Description[@rdf:about="Photoshop"]') }
|
254
|
+
let(:avm) { xml.at_xpath('//rdf:Description[@rdf:about="AVM"]') }
|
255
|
+
|
256
|
+
context 'nothing in it' do
|
257
|
+
it "should have basic tags" do
|
258
|
+
xml.at_xpath('//rdf:RDF').should_not be_nil
|
259
|
+
xml.search('//rdf:RDF/rdf:Description').should_not be_empty
|
260
|
+
photoshop.at_xpath('./photoshop:DateCreated').should_not be_nil
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
context 'with basics' do
|
265
|
+
with_all_options
|
266
|
+
|
267
|
+
def xpath_text(which, xpath)
|
268
|
+
which.at_xpath(xpath).text
|
269
|
+
end
|
270
|
+
|
271
|
+
def xpath_list(which, xpath, search = './/rdf:li')
|
272
|
+
which.at_xpath(xpath).search(search).collect(&:text)
|
273
|
+
end
|
274
|
+
|
275
|
+
it "should have the image info tags" do
|
276
|
+
xpath_text(dublin_core, './dc:title/rdf:Alt/rdf:li').should == title
|
277
|
+
xpath_text(photoshop, './photoshop:Headline').should == headline
|
278
|
+
xpath_text(dublin_core, './dc:description/rdf:Alt/rdf:li').should == description
|
279
|
+
|
280
|
+
xpath_text(avm, './avm:Distance.Notes').should == distance_notes
|
281
|
+
xpath_text(avm, './avm:Spectral.Notes').should == spectral_notes
|
282
|
+
xpath_text(avm, './avm:ReferenceURL').should == reference_url
|
283
|
+
xpath_text(photoshop, './photoshop:Credit').should == credit
|
284
|
+
xpath_text(photoshop, './photoshop:DateCreated').should == date
|
285
|
+
xpath_text(avm, './avm:ID').should == id
|
286
|
+
xpath_text(avm, './avm:Type').should == type
|
287
|
+
xpath_text(avm, './avm:Image.ProductQuality').should == image_quality
|
288
|
+
end
|
289
|
+
|
290
|
+
it "should have the spatial tags" do
|
291
|
+
xpath_text(avm, './avm:Spatial.CoordinateFrame').should == coordinate_frame
|
292
|
+
xpath_text(avm, './avm:Spatial.Equinox').should == equinox
|
293
|
+
xpath_list(avm, './avm:Spatial.ReferenceValue').should == reference_value.collect { |v| v.to_f.to_s }
|
294
|
+
xpath_list(avm, './avm:Spatial.ReferenceDimension').should == reference_dimension.collect { |v| v.to_f.to_s }
|
295
|
+
xpath_list(avm, './avm:Spatial.ReferencePixel').should == reference_pixel.collect { |v| v.to_f.to_s }
|
296
|
+
xpath_list(avm, './avm:Spatial.Scale').should == spatial_scale.collect { |v| v.to_f.to_s }
|
297
|
+
xpath_text(avm, './avm:Spatial.CoordsystemProjection').should == coordinate_system_projection
|
298
|
+
xpath_text(avm, './avm:Spatial.Quality').should == spatial_quality
|
299
|
+
xpath_text(avm, './avm:Spatial.Notes').should == spatial_notes
|
300
|
+
xpath_text(avm, './avm:Spatial.FITSheader').should == fits_header
|
301
|
+
xpath_list(avm, './avm:Spatial.CDMatrix').should == spatial_cd_matrix.collect { |v| v.to_f.to_s }
|
302
|
+
end
|
303
|
+
|
304
|
+
it "should have the publisher tags" do
|
305
|
+
xpath_text(avm, './avm:Publisher').should == publisher
|
306
|
+
xpath_text(avm, './avm:PublisherID').should == publisher_id
|
307
|
+
xpath_text(avm, './avm:ResourceID').should == resource_id
|
308
|
+
xpath_text(avm, './avm:ResourceURL').should == resource_url
|
309
|
+
xpath_list(avm, './avm:RelatedResources', './rdf:Bag/rdf:li').should == related_resources
|
310
|
+
xpath_text(avm, './avm:MetadataDate').should == metadata_date
|
311
|
+
xpath_text(avm, './avm:MetadataVersion').should == metadata_version
|
312
|
+
end
|
313
|
+
|
314
|
+
context "distance" do
|
315
|
+
context "no distances" do
|
316
|
+
let(:redshift) { nil }
|
317
|
+
let(:light_years) { nil }
|
318
|
+
|
319
|
+
it("should have no distances") { avm.at_xpath('./avm:Distance').should be_nil }
|
320
|
+
end
|
321
|
+
|
322
|
+
context "redshift only" do
|
323
|
+
let(:light_years) { nil }
|
324
|
+
|
325
|
+
it "should have redshift only" do
|
326
|
+
avm.at_xpath('./avm:Distance/rdf:Seq/rdf:li[1]').text.should == '-'
|
327
|
+
avm.at_xpath('./avm:Distance/rdf:Seq/rdf:li[2]').text.should == redshift
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
context "light years only" do
|
332
|
+
let(:redshift) { nil }
|
333
|
+
|
334
|
+
it "should should have light years but not redshift" do
|
335
|
+
avm.at_xpath('./avm:Distance/rdf:Seq/rdf:li[1]').text.should == light_years
|
336
|
+
avm.at_xpath('./avm:Distance/rdf:Seq/rdf:li[2]').should be_nil
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
context "redshift and light years" do
|
341
|
+
it "should have both light years and redshift" do
|
342
|
+
avm.at_xpath('./avm:Distance/rdf:Seq/rdf:li[1]').text.should == light_years
|
343
|
+
avm.at_xpath('./avm:Distance/rdf:Seq/rdf:li[2]').text.should == redshift
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|