finish serializing creators

This commit is contained in:
John Bintz 2011-03-10 17:45:21 -05:00
parent 59320b3420
commit 29449d381b
9 changed files with 199 additions and 35 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
.bundle .bundle
Gemfile.lock Gemfile.lock
pkg/* pkg/*
.quickfix.txt

5
.rspec
View File

@ -1 +1,6 @@
-c -c
--require ./spec/quick_fix_formatter.rb
--format progress
--format RSpec::Core::Formatters::QuickFixFormatter
--out .quickfix.txt

View File

@ -3,13 +3,15 @@ require 'nokogiri'
module AVM module AVM
class Creator 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 = {} @options = {}
@contacts = [] @contacts = []
@image = image
end end
def merge!(hash) def merge!(hash)
@ -28,12 +30,31 @@ module AVM
end end
end end
def add_to_rdf(rdf) def add_to_document(document)
creator = rdf.add_child('<dc:creator><rdf:Seq></rdf:Seq></dc:creator>') document.add_to_doc do |refs|
creator = refs[:dublin_core].add_child('<dc:creator><rdf:Seq></rdf:Seq></dc:creator>')
list = creator.at_xpath('.//rdf:Seq')
contacts.sort.each { |contact| list.add_child(contact.to_creator_list_element) } list = creator.at_xpath('.//rdf:Seq')
contact_info = refs[:iptc].add_child('<Iptc4xmpCore:CreatorContactInfo rdf:parseType="Resource" />').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 "<Iptc4xmpCore:#{element_name}>#{contacts.sort.collect(&key).join(',')}</Iptc4xmpCore:#{element_name}>"
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 end
def primary_contact def primary_contact

View File

@ -1,40 +1,21 @@
require 'avm/creator' require 'avm/creator'
require 'avm/xmp'
module AVM module AVM
class Image class Image
attr_reader :creator attr_reader :creator
def initialize def initialize
@creator = AVM::Creator.new @creator = AVM::Creator.new(self)
end end
def to_xml 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.doc
document
end end
private
def empty_xml_doc
document = Nokogiri::XML(<<-XML)
<x:xmpmeta xmlns:x="adobe:ns:meta/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:RDF></rdf:RDF></x:xmpmeta>
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
end end

55
lib/avm/xmp.rb Normal file
View File

@ -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)
<x:xmpmeta xmlns:x="adobe:ns:meta/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:RDF>
<rdf:Description about="Dublin Core">
</rdf:Description>
<rdf:Description about="IPTC">
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
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

View File

@ -95,8 +95,11 @@ describe AVM::Creator do
let(:first_name) { 'John' } let(:first_name) { 'John' }
let(:second_name) { 'Zohn' } let(:second_name) { 'Zohn' }
let(:first_contact) { creator.create_contact(:name => first_name) } let(:first_contact) { creator.create_contact(first_contact_options) }
let(:second_contact) { creator.create_contact(:name => second_name) } 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 } } 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 ] } it { should == [ first_name, second_name ] }
end 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
end end

18
spec/avm/xmp_spec.rb Normal file
View File

@ -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] << "<rdf:addedToDublinCore />"
refs[:iptc] << "<rdf:addedToIPTC />"
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

View File

@ -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

View File

@ -1,4 +1,4 @@
RSpec.configure do |config| RSpec.configure do |config|
config.mock_with :mocha config.mock_with :mocha
end end