From 29449d381bd415ed8f33fb05e1a8647aeb4d449e Mon Sep 17 00:00:00 2001 From: John Bintz Date: Thu, 10 Mar 2011 17:45:21 -0500 Subject: [PATCH] finish serializing creators --- .gitignore | 1 + .rspec | 5 +++ lib/avm/creator.rb | 37 +++++++++++++++++----- lib/avm/image.rb | 29 +++--------------- lib/avm/xmp.rb | 55 +++++++++++++++++++++++++++++++++ spec/avm/creator_spec.rb | 61 +++++++++++++++++++++++++++++++++++-- spec/avm/xmp_spec.rb | 18 +++++++++++ spec/quick_fix_formatter.rb | 26 ++++++++++++++++ spec/spec_helper.rb | 2 +- 9 files changed, 199 insertions(+), 35 deletions(-) create mode 100644 lib/avm/xmp.rb create mode 100644 spec/avm/xmp_spec.rb create mode 100644 spec/quick_fix_formatter.rb 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 -