diff --git a/lib/avm/contact.rb b/lib/avm/contact.rb index 00dff9b..62ecfa0 100644 --- a/lib/avm/contact.rb +++ b/lib/avm/contact.rb @@ -20,5 +20,9 @@ module AVM def <=>(other) self.name <=> other.name end + + def to_creator_list_element + %{#{self.name}} + end end end diff --git a/lib/avm/creator.rb b/lib/avm/creator.rb index 7e9fb85..65bac09 100644 --- a/lib/avm/creator.rb +++ b/lib/avm/creator.rb @@ -1,9 +1,12 @@ require 'avm/contact' +require 'nokogiri' module AVM class Creator attr_reader :contacts + PRIMARY_CONTACT_FIELDS = [ :address, :city, :state, :province, :postal_code, :zip, :country ] + def initialize @options = {} @contacts = [] @@ -13,18 +16,36 @@ module AVM @options.merge!(hash) end - def address - primary_contact_field :address - end - def method_missing(key, *opts) if key.to_s[-1..-1] == '=' @options[key.to_s[0..-2].to_sym] = opts.first else - @options[key] + if PRIMARY_CONTACT_FIELDS.include?(key) + primary_contact_field key + else + @options[key] + end end end + def add_to_rdf(rdf) + creator = rdf.add_child('') + + list = creator.at_xpath('.//rdf:Seq') + + contacts.sort.each { |contact| list.add_child(contact.to_creator_list_element) } + end + + def primary_contact + @contacts.find(&:primary) || @contacts.sort.first + end + + def create_contact(info) + contact = Contact.new(info) + contacts << contact + contact + end + private def primary_contact_field(field) if contact = primary_contact @@ -33,10 +54,6 @@ module AVM nil end end - - def primary_contact - @contacts.find(&:primary) || @contacts.sort.first - end end end diff --git a/lib/avm/image.rb b/lib/avm/image.rb index 1e99bd3..6ba015f 100644 --- a/lib/avm/image.rb +++ b/lib/avm/image.rb @@ -7,6 +7,34 @@ module AVM def initialize @creator = AVM::Creator.new end + + def to_xml + document = empty_xml_doc + + rdf = document.at_xpath('//rdf:RDF') + + creator.add_to_rdf(rdf) + + document + 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/ruby-avm-library.gemspec b/ruby-avm-library.gemspec index beb794d..ef7efee 100644 --- a/ruby-avm-library.gemspec +++ b/ruby-avm-library.gemspec @@ -21,4 +21,6 @@ Gem::Specification.new do |s| s.add_development_dependency 'rspec' s.add_development_dependency 'mocha' + + s.add_dependency 'nokogiri' end diff --git a/spec/avm/contact_spec.rb b/spec/avm/contact_spec.rb index c28371f..0c3e8df 100644 --- a/spec/avm/contact_spec.rb +++ b/spec/avm/contact_spec.rb @@ -37,6 +37,8 @@ describe AVM::Contact do its(:zip) { should == postal_code } its(:country) { should == country } + its(:to_creator_list_element) { should == "John Bintz" } + describe 'mappings' do AVM::Contact::FIELD_MAP.each do |key, value| context "#{key} => #{value}" do diff --git a/spec/avm/creator_spec.rb b/spec/avm/creator_spec.rb index 87ceb2a..42d9546 100644 --- a/spec/avm/creator_spec.rb +++ b/spec/avm/creator_spec.rb @@ -40,29 +40,80 @@ describe AVM::Creator do end context 'one contact, must be primary' do - let(:first_contact) { AVM::Contact.new(:name => 'zz bill', :address => first_contact_address) } + let(:first_contact) { AVM::Contact.new( + :name => 'zz bill', + :address => first_contact_address, + :city => first_contact_address, + :state => first_contact_address, + :postal_code => first_contact_address, + :country => first_contact_address + ) } let(:first_contact_address) { 'first contact' } before { creator.contacts << first_contact } - its(:address) { should == first_contact_address } + fields = [ :address, :city, :state, :province, :postal_code, :zip, :country ] + fields.each { |field| its(field) { should == first_contact_address } } context 'two contacts' do - let(:second_contact) { AVM::Contact.new(:name => 'aa bill', :address => second_contact_address) } + let(:second_contact) { AVM::Contact.new( + :name => 'aa bill', + :address => second_contact_address, + :city => second_contact_address, + :state => second_contact_address, + :postal_code => second_contact_address, + :country => second_contact_address + ) } let(:second_contact_address) { 'second contact' } before { creator.contacts << second_contact } context 'no primary, first alphabetical is primary' do - its(:address) { should == second_contact_address } + fields.each { |field| its(field) { should == second_contact_address } } end context 'one is primary, use it' do before { first_contact.primary = true } - its(:address) { should == first_contact_address } + fields.each { |field| its(field) { should == first_contact_address } } end end end end + + describe '#create_contact' do + let(:first_name) { 'John' } + let(:first_contact) { creator.create_contact(:name => first_name) } + + subject { creator.primary_contact } + before { first_contact } + + its(:name) { should == first_name } + end + + describe 'contact name node' 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) } + + subject { image.to_xml.search('//dc:creator/rdf:Seq/rdf:li').collect { |node| node.text } } + + context 'no contacts' do + it { should == [] } + end + + context 'one contact' do + before { first_contact } + + it { should == [ first_name ] } + end + + context 'second contact' do + before { second_contact ; first_contact } + + it { should == [ first_name, second_name ] } + end + end end diff --git a/spec/avm/image_spec.rb b/spec/avm/image_spec.rb index ff60f5e..a043fa5 100644 --- a/spec/avm/image_spec.rb +++ b/spec/avm/image_spec.rb @@ -11,5 +11,14 @@ describe AVM::Image do its(:creator) { should be_a_kind_of(AVM::Creator) } end + + describe '#to_xml' do + let(:xml) { image.to_xml } + + context 'nothing in it' do + subject { xml.at_xpath('//rdf:RDF').should_not be_nil } + subject { xml.search('//rdf:RDF/rdf:Description').should be_empty } + end + end end