read one creator
This commit is contained in:
parent
29449d381b
commit
efff98eb32
|
@ -7,10 +7,13 @@ module AVM
|
||||||
|
|
||||||
IPTC_CORE_FIELDS = [ :address, :city, :state, :zip, :country ]
|
IPTC_CORE_FIELDS = [ :address, :city, :state, :zip, :country ]
|
||||||
PRIMARY_CONTACT_FIELDS = IPTC_CORE_FIELDS + [ :province, :postal_code ]
|
PRIMARY_CONTACT_FIELDS = IPTC_CORE_FIELDS + [ :province, :postal_code ]
|
||||||
|
IPTC_MULTI_FIELD_MAP = [ [ :telephone, 'CiTelWork' ], [ :email, 'CiEmailWork' ] ]
|
||||||
|
IPTC_CORE_FIELD_ELEMENT_NAMES = %w{CiAdrExtadr CiAdrCity CiAdrRegion CiAdrPcode CiAdrCtry}
|
||||||
|
IPTC_CORE_FIELDS_AND_NAMES = IPTC_CORE_FIELDS.zip(IPTC_CORE_FIELD_ELEMENT_NAMES)
|
||||||
|
|
||||||
def initialize(image)
|
def initialize(image, given_contacts = [])
|
||||||
@options = {}
|
@options = {}
|
||||||
@contacts = []
|
@contacts = given_contacts
|
||||||
@image = image
|
@image = image
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -18,6 +21,14 @@ module AVM
|
||||||
@options.merge!(hash)
|
@options.merge!(hash)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def length
|
||||||
|
contacts.length
|
||||||
|
end
|
||||||
|
|
||||||
|
def [](which)
|
||||||
|
contacts[which]
|
||||||
|
end
|
||||||
|
|
||||||
def method_missing(key, *opts)
|
def method_missing(key, *opts)
|
||||||
if key.to_s[-1..-1] == '='
|
if key.to_s[-1..-1] == '='
|
||||||
@options[key.to_s[0..-2].to_sym] = opts.first
|
@options[key.to_s[0..-2].to_sym] = opts.first
|
||||||
|
@ -31,7 +42,7 @@ module AVM
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_to_document(document)
|
def add_to_document(document)
|
||||||
document.add_to_doc do |refs|
|
document.get_refs do |refs|
|
||||||
creator = refs[:dublin_core].add_child('<dc:creator><rdf:Seq></rdf:Seq></dc:creator>')
|
creator = refs[:dublin_core].add_child('<dc:creator><rdf:Seq></rdf:Seq></dc:creator>')
|
||||||
|
|
||||||
list = creator.at_xpath('.//rdf:Seq')
|
list = creator.at_xpath('.//rdf:Seq')
|
||||||
|
@ -42,13 +53,13 @@ module AVM
|
||||||
end
|
end
|
||||||
|
|
||||||
if primary_contact
|
if primary_contact
|
||||||
[ [ :telephone, 'CiTelWork' ], [ :email, 'CiEmailWork' ] ].each do |key, element_name|
|
IPTC_MULTI_FIELD_MAP.each do |key, element_name|
|
||||||
contact_info.add_child "<Iptc4xmpCore:#{element_name}>#{contacts.sort.collect(&key).join(',')}</Iptc4xmpCore:#{element_name}>"
|
contact_info.add_child "<Iptc4xmpCore:#{element_name}>#{contacts.sort.collect(&key).join(',')}</Iptc4xmpCore:#{element_name}>"
|
||||||
end
|
end
|
||||||
|
|
||||||
iptc_namespace = document.doc.root.namespace_scopes.find { |ns| ns.prefix == 'Iptc4xmpCore' }
|
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|
|
IPTC_CORE_FIELDS_AND_NAMES.each do |key, element_name|
|
||||||
node = contact_info.document.create_element(element_name, primary_contact.send(key))
|
node = contact_info.document.create_element(element_name, primary_contact.send(key))
|
||||||
node.namespace = iptc_namespace
|
node.namespace = iptc_namespace
|
||||||
contact_info.add_child node
|
contact_info.add_child node
|
||||||
|
@ -57,6 +68,31 @@ module AVM
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def from_xml(image, document)
|
||||||
|
contacts = []
|
||||||
|
document.get_refs do |refs|
|
||||||
|
refs[:dublin_core].search('.//rdf:li').each do |name|
|
||||||
|
contacts << { :name => name.text }
|
||||||
|
end
|
||||||
|
|
||||||
|
IPTC_MULTI_FIELD_MAP.each do |key, element_name|
|
||||||
|
if node = refs[:iptc].at_xpath("//Iptc4xmpCore:#{element_name}")
|
||||||
|
node.text.split(',').collect(&:strip).each_with_index do |value, index|
|
||||||
|
contacts[index][key] = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
IPTC_CORE_FIELDS_AND_NAMES.each do |key, element_name|
|
||||||
|
if node = refs[:iptc].at_xpath("//Iptc4xmpCore:#{element_name}")
|
||||||
|
contacts.first[key] = node.text.strip
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@contacts = contacts.collect { |contact| Contact.new(contact) }
|
||||||
|
end
|
||||||
|
|
||||||
def primary_contact
|
def primary_contact
|
||||||
@contacts.find(&:primary) || @contacts.sort.first
|
@contacts.find(&:primary) || @contacts.sort.first
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,6 +16,14 @@ module AVM
|
||||||
|
|
||||||
document.doc
|
document.doc
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.from_xml(string)
|
||||||
|
document = AVM::XMP.from_string(string)
|
||||||
|
|
||||||
|
image = new
|
||||||
|
image.creator.from_xml(self, document)
|
||||||
|
image
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,15 +4,49 @@ module AVM
|
||||||
class XMP
|
class XMP
|
||||||
attr_reader :doc
|
attr_reader :doc
|
||||||
|
|
||||||
def initialize
|
def initialize(doc = nil)
|
||||||
@doc = empty_xml_doc
|
@doc = doc || empty_xml_doc
|
||||||
|
ensure_namespaces!
|
||||||
|
ensure_descriptions_findable!
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_to_doc
|
def get_refs
|
||||||
yield Hash[[ :dublin_core, :iptc ].collect { |key| [ key, send(key) ] }]
|
yield Hash[[ :dublin_core, :iptc ].collect { |key| [ key, send(key) ] }]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.from_string(string)
|
||||||
|
new(Nokogiri::XML(string))
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
def ensure_namespaces!
|
||||||
|
{
|
||||||
|
:x => "adobe:ns:meta/",
|
||||||
|
:rdf => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
|
||||||
|
: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|
|
||||||
|
doc.root.add_namespace_definition(namespace.to_s, url)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def ensure_descriptions_findable!
|
||||||
|
doc.search('//rdf:Description').each do |description|
|
||||||
|
if first_child = description.first_element_child
|
||||||
|
if first_child.namespace
|
||||||
|
case first_child.namespace.prefix
|
||||||
|
when 'dc'
|
||||||
|
description['about'] = 'Dublin Core'
|
||||||
|
when 'Iptc4xmpCore'
|
||||||
|
description['about'] = 'IPTC'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def dublin_core
|
def dublin_core
|
||||||
at_rdf_description "Dublin Core"
|
at_rdf_description "Dublin Core"
|
||||||
end
|
end
|
||||||
|
@ -26,7 +60,7 @@ module AVM
|
||||||
end
|
end
|
||||||
|
|
||||||
def empty_xml_doc
|
def empty_xml_doc
|
||||||
document = Nokogiri::XML(<<-XML)
|
Nokogiri::XML(<<-XML)
|
||||||
<x:xmpmeta xmlns:x="adobe:ns:meta/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
<x:xmpmeta xmlns:x="adobe:ns:meta/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||||
<rdf:RDF>
|
<rdf:RDF>
|
||||||
<rdf:Description about="Dublin Core">
|
<rdf:Description about="Dublin Core">
|
||||||
|
@ -38,17 +72,6 @@ module AVM
|
||||||
</rdf:RDF>
|
</rdf:RDF>
|
||||||
</x:xmpmeta>
|
</x:xmpmeta>
|
||||||
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -91,6 +91,51 @@ describe AVM::Creator do
|
||||||
its(:name) { should == first_name }
|
its(:name) { should == first_name }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#from_xml' do
|
||||||
|
let(:document) { image.to_xml }
|
||||||
|
let(:image) { AVM::Image.from_xml(File.read(file_path)) }
|
||||||
|
|
||||||
|
subject { image }
|
||||||
|
|
||||||
|
context 'no creator' do
|
||||||
|
let(:file_path) { 'spec/sample_files/creator/no_creator.xmp' }
|
||||||
|
|
||||||
|
its('creator.length') { should == 0 }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'one creator' do
|
||||||
|
let(:file_path) { 'spec/sample_files/creator/one_creator.xmp' }
|
||||||
|
|
||||||
|
its('creator.length') { should == 1 }
|
||||||
|
|
||||||
|
context 'creator one' do
|
||||||
|
subject { image.creator[0] }
|
||||||
|
|
||||||
|
let(:name) { 'John Bintz' }
|
||||||
|
let(:email) { 'bintz@stsci.edu' }
|
||||||
|
let(:telephone) { '800-555-1234' }
|
||||||
|
let(:address) { '3700 San Martin Drive' }
|
||||||
|
let(:city) { 'Baltimore' }
|
||||||
|
let(:state) { 'Maryland' }
|
||||||
|
let(:zip) { '21218' }
|
||||||
|
let(:country) { 'USA' }
|
||||||
|
|
||||||
|
its(:name) { should == name }
|
||||||
|
its(:address) { should == address }
|
||||||
|
its(:city) { should == city }
|
||||||
|
its(:state) { should == state }
|
||||||
|
its(:zip) { should == zip }
|
||||||
|
its(:country) { should == country }
|
||||||
|
its(:email) { should == email }
|
||||||
|
its(:telephone) { should == telephone }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'two creators' do
|
||||||
|
let(:file_path) { 'spec/sample_files/creator/two_creators.xmp' }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'contact name node' do
|
describe 'contact name node' do
|
||||||
let(:first_name) { 'John' }
|
let(:first_name) { 'John' }
|
||||||
let(:second_name) { 'Zohn' }
|
let(:second_name) { 'Zohn' }
|
||||||
|
|
|
@ -4,9 +4,11 @@ require 'avm/xmp'
|
||||||
describe AVM::XMP do
|
describe AVM::XMP do
|
||||||
let(:xmp) { self.class.describes.new }
|
let(:xmp) { self.class.describes.new }
|
||||||
|
|
||||||
describe '#add_to_doc' do
|
subject { xmp }
|
||||||
|
|
||||||
|
describe '#get_refs' do
|
||||||
before {
|
before {
|
||||||
xmp.add_to_doc do |refs|
|
xmp.get_refs do |refs|
|
||||||
refs[:dublin_core] << "<rdf:addedToDublinCore />"
|
refs[:dublin_core] << "<rdf:addedToDublinCore />"
|
||||||
refs[:iptc] << "<rdf:addedToIPTC />"
|
refs[:iptc] << "<rdf:addedToIPTC />"
|
||||||
end
|
end
|
||||||
|
@ -15,4 +17,46 @@ describe AVM::XMP do
|
||||||
specify { xmp.doc.at_xpath('//rdf:Description[@about="Dublin Core"]//rdf:addedToDublinCore').should_not be_nil }
|
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 }
|
specify { xmp.doc.at_xpath('//rdf:Description[@about="IPTC"]//rdf:addedToIPTC').should_not be_nil }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '.from_string' do
|
||||||
|
let(:xmp) { self.class.describes.from_string(string) }
|
||||||
|
let(:string) { '<xml><node /></xml>' }
|
||||||
|
|
||||||
|
specify { xmp.doc.at_xpath('//node').should_not be_nil }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#ensure_descriptions_findable!' do
|
||||||
|
let(:document) { <<-XML }
|
||||||
|
<x:xmpmeta xmlns:x="adobe:ns:meta/">
|
||||||
|
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||||
|
#{content}
|
||||||
|
</rdf:RDF>
|
||||||
|
</x:xmpmeta>
|
||||||
|
XML
|
||||||
|
|
||||||
|
let(:xmp) { self.class.describes.new(Nokogiri::XML(document)) }
|
||||||
|
|
||||||
|
context 'no nodes within' do
|
||||||
|
let(:content) { '' }
|
||||||
|
|
||||||
|
[ 'Dublin Core', 'IPTC' ].each do |which|
|
||||||
|
specify { xmp.doc.at_xpath(%{//rdf:Description[@about="#{which}"]}).should be_nil }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'has identifying nodes within' do
|
||||||
|
let(:content) { <<-XML }
|
||||||
|
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<dc:creator />
|
||||||
|
</rdf:Description>
|
||||||
|
<rdf:Description rdf:about="" xmlns:Iptc4xmpCore="http://itpc.org/stf/Iptc4xmpCore/1.0/xmlns/">
|
||||||
|
<Iptc4xmpCore:CreatorContactInfo rdf:parseType="Resource" />
|
||||||
|
</rdf:Description>
|
||||||
|
XML
|
||||||
|
|
||||||
|
[ 'Dublin Core', 'IPTC' ].each do |which|
|
||||||
|
specify { xmp.doc.at_xpath(%{//rdf:Description[@about="#{which}"]}).should_not be_nil }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.2-c063 53.352624, 2008/07/30-18:05:41 ">
|
||||||
|
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||||
|
<rdf:Description rdf:about=""
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<dc:creator />
|
||||||
|
</rdf:Description>
|
||||||
|
<rdf:Description rdf:about=""
|
||||||
|
xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/">
|
||||||
|
<Iptc4xmpCore:CreatorContactInfo rdf:parseType="Resource">
|
||||||
|
</Iptc4xmpCore:CreatorContactInfo>
|
||||||
|
</rdf:Description>
|
||||||
|
</rdf:RDF>
|
||||||
|
</x:xmpmeta>
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.2-c063 53.352624, 2008/07/30-18:05:41 ">
|
||||||
|
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||||
|
<rdf:Description rdf:about=""
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<dc:creator>
|
||||||
|
<rdf:Seq><rdf:li>John Bintz</rdf:li></rdf:Seq>
|
||||||
|
</dc:creator>
|
||||||
|
</rdf:Description>
|
||||||
|
<rdf:Description rdf:about=""
|
||||||
|
xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/">
|
||||||
|
<Iptc4xmpCore:CreatorContactInfo rdf:parseType="Resource">
|
||||||
|
<Iptc4xmpCore:CiAdrExtadr>3700 San Martin Drive</Iptc4xmpCore:CiAdrExtadr>
|
||||||
|
<Iptc4xmpCore:CiAdrCity>Baltimore</Iptc4xmpCore:CiAdrCity>
|
||||||
|
<Iptc4xmpCore:CiAdrRegion>Maryland</Iptc4xmpCore:CiAdrRegion>
|
||||||
|
<Iptc4xmpCore:CiAdrPcode>21218</Iptc4xmpCore:CiAdrPcode>
|
||||||
|
<Iptc4xmpCore:CiAdrCtry>USA</Iptc4xmpCore:CiAdrCtry>
|
||||||
|
<Iptc4xmpCore:CiTelWork>800-555-1234</Iptc4xmpCore:CiTelWork>
|
||||||
|
<Iptc4xmpCore:CiEmailWork>bintz@stsci.edu</Iptc4xmpCore:CiEmailWork>
|
||||||
|
<Iptc4xmpCore:CiUrlWork>http://hubblesite.org</Iptc4xmpCore:CiUrlWork>
|
||||||
|
</Iptc4xmpCore:CreatorContactInfo>
|
||||||
|
</rdf:Description>
|
||||||
|
</rdf:RDF>
|
||||||
|
</x:xmpmeta>
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
RSpec.configure do |config|
|
RSpec.configure do |config|
|
||||||
config.mock_with :mocha
|
config.mock_with :mocha
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue