diff --git a/.gitignore b/.gitignore
index 4040c6c..7daf373 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
.bundle
Gemfile.lock
pkg/*
+.quickfix.txt
diff --git a/.rspec b/.rspec
index b71bde1..ae67f9d 100644
--- a/.rspec
+++ b/.rspec
@@ -1 +1,6 @@
-c
+--require ./spec/quick_fix_formatter.rb
+--format progress
+--format RSpec::Core::Formatters::QuickFixFormatter
+--out .quickfix.txt
+
diff --git a/lib/avm/creator.rb b/lib/avm/creator.rb
index 65bac09..fe3c6a8 100644
--- a/lib/avm/creator.rb
+++ b/lib/avm/creator.rb
@@ -3,13 +3,15 @@ require 'nokogiri'
module AVM
class Creator
- attr_reader :contacts
+ attr_reader :contacts, :image
- PRIMARY_CONTACT_FIELDS = [ :address, :city, :state, :province, :postal_code, :zip, :country ]
+ IPTC_CORE_FIELDS = [ :address, :city, :state, :zip, :country ]
+ PRIMARY_CONTACT_FIELDS = IPTC_CORE_FIELDS + [ :province, :postal_code ]
- def initialize
+ def initialize(image)
@options = {}
@contacts = []
+ @image = image
end
def merge!(hash)
@@ -28,12 +30,31 @@ module AVM
end
end
- def add_to_rdf(rdf)
- creator = rdf.add_child('')
-
- list = creator.at_xpath('.//rdf:Seq')
+ def add_to_document(document)
+ document.add_to_doc do |refs|
+ creator = refs[:dublin_core].add_child('')
- contacts.sort.each { |contact| list.add_child(contact.to_creator_list_element) }
+ list = creator.at_xpath('.//rdf:Seq')
+ contact_info = refs[:iptc].add_child('').first
+
+ contacts.sort.each do |contact|
+ list.add_child(contact.to_creator_list_element)
+ end
+
+ if primary_contact
+ [ [ :telephone, 'CiTelWork' ], [ :email, 'CiEmailWork' ] ].each do |key, element_name|
+ contact_info.add_child "#{contacts.sort.collect(&key).join(',')}"
+ end
+
+ iptc_namespace = document.doc.root.namespace_scopes.find { |ns| ns.prefix == 'Iptc4xmpCore' }
+
+ IPTC_CORE_FIELDS.zip(%w{CiAdrExtadr CiAdrCity CiAdrRegion CiAdrPcode CiAdrCtry}).each do |key, element_name|
+ node = contact_info.document.create_element(element_name, primary_contact.send(key))
+ node.namespace = iptc_namespace
+ contact_info.add_child node
+ end
+ end
+ end
end
def primary_contact
diff --git a/lib/avm/image.rb b/lib/avm/image.rb
index 6ba015f..3f89423 100644
--- a/lib/avm/image.rb
+++ b/lib/avm/image.rb
@@ -1,40 +1,21 @@
require 'avm/creator'
+require 'avm/xmp'
module AVM
class Image
attr_reader :creator
def initialize
- @creator = AVM::Creator.new
+ @creator = AVM::Creator.new(self)
end
def to_xml
- document = empty_xml_doc
+ document = AVM::XMP.new
- rdf = document.at_xpath('//rdf:RDF')
+ creator.add_to_document(document)
- creator.add_to_rdf(rdf)
-
- document
+ document.doc
end
-
- private
- def empty_xml_doc
- document = Nokogiri::XML(<<-XML)
-
- XML
-
- {
- :dc => "http://purl.org/dc/elements/1.1/",
- :photoshop => "http://ns.adobe.com/photoshop/1.0/",
- :avm => "http://www.communicatingastronomy.org/avm/1.0/",
- :Iptc4xmlCore => "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/"
- }.each do |namespace, url|
- document.root.add_namespace_definition(namespace.to_s, url)
- end
-
- document
- end
end
end
diff --git a/lib/avm/xmp.rb b/lib/avm/xmp.rb
new file mode 100644
index 0000000..aab7e77
--- /dev/null
+++ b/lib/avm/xmp.rb
@@ -0,0 +1,55 @@
+require 'nokogiri'
+
+module AVM
+ class XMP
+ attr_reader :doc
+
+ def initialize
+ @doc = empty_xml_doc
+ end
+
+ def add_to_doc
+ yield Hash[[ :dublin_core, :iptc ].collect { |key| [ key, send(key) ] }]
+ end
+
+ private
+ def dublin_core
+ at_rdf_description "Dublin Core"
+ end
+
+ def iptc
+ at_rdf_description "IPTC"
+ end
+
+ def at_rdf_description(about)
+ @doc.at_xpath(%{//rdf:Description[@about="#{about}"]})
+ end
+
+ def empty_xml_doc
+ document = Nokogiri::XML(<<-XML)
+
+
+
+
+
+
+
+
+
+
+ XML
+
+ {
+ :dc => "http://purl.org/dc/elements/1.1/",
+ :photoshop => "http://ns.adobe.com/photoshop/1.0/",
+ :avm => "http://www.communicatingastronomy.org/avm/1.0/",
+ :Iptc4xmpCore => "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/"
+ }.each do |namespace, url|
+ document.root.add_namespace_definition(namespace.to_s, url)
+ end
+
+ document
+ end
+ end
+end
+
diff --git a/spec/avm/creator_spec.rb b/spec/avm/creator_spec.rb
index 42d9546..dfcd79e 100644
--- a/spec/avm/creator_spec.rb
+++ b/spec/avm/creator_spec.rb
@@ -95,8 +95,11 @@ describe AVM::Creator do
let(:first_name) { 'John' }
let(:second_name) { 'Zohn' }
- let(:first_contact) { creator.create_contact(:name => first_name) }
- let(:second_contact) { creator.create_contact(:name => second_name) }
+ let(:first_contact) { creator.create_contact(first_contact_options) }
+ let(:second_contact) { creator.create_contact(second_contact_options) }
+
+ let(:first_contact_options) { { :name => first_name } }
+ let(:second_contact_options) { { :name => second_name } }
subject { image.to_xml.search('//dc:creator/rdf:Seq/rdf:li').collect { |node| node.text } }
@@ -115,5 +118,59 @@ describe AVM::Creator do
it { should == [ first_name, second_name ] }
end
+
+ describe 'everything else uses primary' do
+ let(:fields) { [ :address, :city, :state, :zip, :country ] }
+
+ def other_fields(what)
+ Hash[fields.zip(Array.new(fields.length, what))]
+ end
+
+ let(:first_contact_options) { { :name => first_name }.merge(other_fields('one')) }
+ let(:second_contact_options) { { :name => second_name }.merge(other_fields('two')) }
+
+ before { second_contact ; first_contact }
+
+ specify {
+ %w{CiAdrExtadr CiAdrCity CiAdrRegion CiAdrPcode CiAdrCtry}.each do |element_name|
+ image.to_xml.at_xpath("//Iptc4xmpCore:#{element_name}").text.should == 'one'
+ end
+ }
+ end
+
+ describe 'contact emails, telephones' do
+ let(:first_email) { 'bintz@stsci.edu' }
+ let(:second_email) { 'bintz-2@stsci.edu' }
+
+ let(:first_phone) { '123-456-7890' }
+ let(:second_phone) { '234-567-8901' }
+
+ let(:first_contact_options) { { :name => first_name, :email => first_email, :telephone => first_phone } }
+ let(:second_contact_options) { { :name => second_name, :email => second_email, :telephone => second_phone } }
+
+ let(:contact_info) { image.to_xml.search('//Iptc4xmpCore:CreatorContactInfo') }
+
+ let(:telephone_text) { contact_info.at_xpath('./Iptc4xmpCore:CiTelWork').text }
+ let(:email_text) { contact_info.at_xpath('./Iptc4xmpCore:CiEmailWork').text }
+
+ context 'no contacts' do
+ specify { expect { telephone_text }.to raise_error }
+ specify { expect { email_text }.to raise_error }
+ end
+
+ context 'one contact' do
+ before { first_contact }
+
+ specify { telephone_text.should == first_phone }
+ specify { email_text.should == first_email }
+ end
+
+ context 'two contacts' do
+ before { first_contact ; second_contact }
+
+ specify { telephone_text.should == [ first_phone, second_phone ] * ',' }
+ specify { email_text.should == [ first_email, second_email ] * ',' }
+ end
+ end
end
end
diff --git a/spec/avm/xmp_spec.rb b/spec/avm/xmp_spec.rb
new file mode 100644
index 0000000..20cc1f0
--- /dev/null
+++ b/spec/avm/xmp_spec.rb
@@ -0,0 +1,18 @@
+require 'spec_helper'
+require 'avm/xmp'
+
+describe AVM::XMP do
+ let(:xmp) { self.class.describes.new }
+
+ describe '#add_to_doc' do
+ before {
+ xmp.add_to_doc do |refs|
+ refs[:dublin_core] << ""
+ refs[:iptc] << ""
+ end
+ }
+
+ specify { xmp.doc.at_xpath('//rdf:Description[@about="Dublin Core"]//rdf:addedToDublinCore').should_not be_nil }
+ specify { xmp.doc.at_xpath('//rdf:Description[@about="IPTC"]//rdf:addedToIPTC').should_not be_nil }
+ end
+end
diff --git a/spec/quick_fix_formatter.rb b/spec/quick_fix_formatter.rb
new file mode 100644
index 0000000..60df233
--- /dev/null
+++ b/spec/quick_fix_formatter.rb
@@ -0,0 +1,26 @@
+require 'rspec/core/formatters/base_text_formatter'
+
+module RSpec
+ module Core
+ module Formatters
+ class QuickFixFormatter < BaseTextFormatter
+ def dump_summary(duration, example_count, failure_count, pending_count)
+ end
+
+ def dump_profile
+ end
+
+ def dump_pending
+ end
+
+ def dump_failures
+ failed_examples.each do |example|
+ output.puts "%s:%s:%s" % [ example.file_path, example.metadata[:line_number], example.metadata[:execution_result][:exception].message ]
+ end
+ end
+ end
+ end
+ end
+end
+
+
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index eba562b..ae9d63c 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,4 +1,4 @@
+
RSpec.configure do |config|
config.mock_with :mocha
end
-