om 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,160 +0,0 @@
1
- require "open-uri"
2
- require "logger"
3
-
4
- class OM::XML::ParentNodeNotFoundError < RuntimeError; end
5
- module OM::XML::PropertyValueOperators
6
-
7
- def property_values(*lookup_args)
8
- result = []
9
- retrieve(*lookup_args).each {|node| result << node.text }
10
- return result
11
- end
12
-
13
- #
14
- # example properties values hash: {[{":person"=>"0"}, "role", "text"]=>{"0"=>"role1", "1"=>"role2", "2"=>"role3"}, [{:person=>1}, :family_name]=>"Andronicus", [{"person"=>"1"},:given_name]=>["Titus"],[{:person=>1},:role,:text]=>["otherrole1","otherrole2"] }
15
- def update_properties(params={})
16
- # remove any fields from params that this datastream doesn't recognize
17
- params.delete_if do |field_key,new_values|
18
- if field_key.kind_of?(String)
19
- true
20
- else
21
- self.class.accessor_xpath(*OM.destringify(field_key) ).nil?
22
- end
23
- end
24
-
25
- result = params.dup
26
-
27
- params.each_pair do |property_pointer,new_values|
28
- pointer = OM.destringify(property_pointer)
29
- template = OM.pointers_to_flat_array(pointer,false)
30
- hn = self.class.accessor_hierarchical_name(*pointer)
31
-
32
- case new_values
33
- when Hash
34
- when Array
35
- nv = new_values.dup
36
- new_values = {}
37
- nv.each {|v| new_values[nv.index(v).to_s] = v}
38
- else
39
- new_values = {"0"=>new_values}
40
- end
41
-
42
- result.delete(property_pointer)
43
- result[hn] = new_values.dup
44
-
45
- current_values = property_values(*pointer)
46
- new_values.delete_if do |y,z|
47
- if current_values[y.to_i]==z and y.to_i > -1
48
- true
49
- else
50
- false
51
- end
52
- end
53
- xpath = self.class.accessor_xpath(*pointer)
54
- parent_pointer = pointer.dup
55
- parent_pointer.pop
56
- parent_xpath = self.class.accessor_xpath(*parent_pointer)
57
- new_values.each do |y,z|
58
- if retrieve(*pointer)[y.to_i].nil? || y.to_i == -1
59
- result[hn].delete(y)
60
- property_values_append(:parent_select=>parent_xpath,:child_index=>0,:template=>template,:values=>z)
61
- new_array_index = retrieve(*pointer).length - 1
62
- result[hn][new_array_index.to_s] = z
63
- else
64
- property_value_update(xpath, y.to_i, z)
65
- end
66
- end
67
- # current_values.delete_if {|x| x == :delete || x == "" || x == nil}
68
- # instance_eval("#{field_accessor_method}=(current_values)") #write it back to the ds
69
- # result[field_name].delete("-1")
70
- end
71
- return result
72
- end
73
-
74
- def property_values_append(opts={})
75
- parent_select = Array( opts[:parent_select] )
76
- child_index = opts[:child_index]
77
- template = opts[:template]
78
- new_values = Array( opts[:values] )
79
-
80
- # If template is a string, use it as the template, otherwise use it as arguments to builder_template
81
- unless template.instance_of?(String)
82
- template_args = Array(template)
83
- if template_args.last.kind_of?(Hash)
84
- template_opts = template_args.delete_at(template_args.length - 1)
85
- else
86
- template_opts = {}
87
- end
88
- template = self.class.builder_template( template_args, template_opts )
89
- end
90
-
91
- parent_nodeset = lookup(parent_select[0], parent_select[1])
92
- parent_node = node_from_set(parent_nodeset, child_index)
93
-
94
- if parent_node.nil?
95
- raise OM::XML::ParentNodeNotFoundError, "Failed to find a parent node to insert values into based on :parent_select #{parent_select.inspect} with :child_index #{child_index.inspect}"
96
- end
97
-
98
- builder = Nokogiri::XML::Builder.with(parent_node) do |xml|
99
- new_values.each do |builder_new_value|
100
- builder_arg = eval('"'+ template + '"') # this inserts builder_new_value into the builder template
101
- eval(builder_arg)
102
- end
103
- end
104
-
105
- # Nokogiri::XML::Node.new(builder.to_xml, foo)
106
-
107
- return parent_node
108
-
109
- end
110
-
111
- def property_value_update(node_select,child_index,new_value,opts={})
112
- # template = opts.fetch(:template,nil)
113
- node = lookup(node_select, nil)[child_index]
114
- node.content = new_value
115
- end
116
-
117
- # def property_value_set(property_ref, query_opts, node_index, new_value)
118
- # end
119
-
120
- def property_value_delete(opts={})
121
- parent_select = Array( opts[:parent_select] )
122
- parent_index = opts[:parent_index]
123
- child_index = opts[:child_index]
124
- xpath_select = opts[:select]
125
-
126
- if !xpath_select.nil?
127
- node = lookup(xpath_select, nil).first
128
- else
129
- parent_nodeset = lookup(parent_select, parent_select)
130
- # parent_nodeset = lookup(parent_select[0])
131
-
132
- if parent_index.nil?
133
- node = node_from_set(parent_nodeset, child_index)
134
- else
135
- parent = node_from_set(parent_nodeset, parent_index)
136
- # this next line is a hack around the fact that element_children() sometimes doesn't work.
137
- node = node_from_set(parent.xpath("*"), child_index)
138
- end
139
- end
140
-
141
- node.remove
142
- end
143
-
144
-
145
- # Allows you to provide an array index _or_ a symbol representing the function to call on the nodeset in order to retrieve the node.
146
- def node_from_set(nodeset, index)
147
- if index.kind_of?(Integer)
148
- node = nodeset[index]
149
- elsif index.kind_of?(Symbol) && nodeset.respond_to?(index)
150
- node = nodeset.send(index)
151
- else
152
- raise "Could not retrieve node using index #{index}."
153
- end
154
-
155
- return node
156
- end
157
-
158
- private :node_from_set
159
-
160
- end
@@ -1,216 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
- require "nokogiri"
3
- require "om"
4
-
5
- describe "OM::XML::Accessors" do
6
-
7
- before(:all) do
8
- class AccessorTest
9
-
10
- include OM::XML::Container
11
- include OM::XML::Accessors
12
- #accessor :title, :relative_xpath=>[:titleInfo, :title]}}
13
-
14
- accessor :title_info, :relative_xpath=>'oxns:titleInfo', :children=>[
15
- {:main_title=>{:relative_xpath=>'oxns:title'}},
16
- {:language =>{:relative_xpath=>{:attribute=>"lang"} }}
17
- ] # this allows you to access the language attribute as if it was a regular child accessor
18
- accessor :abstract
19
- accessor :topic_tag, :relative_xpath=>'oxns:subject/oxns:topic'
20
- accessor :person, :relative_xpath=>'oxns:name[@type="personal"]', :children=>[
21
- {:last_name=>{:relative_xpath=>'oxns:namePart[@type="family"]'}},
22
- {:first_name=>{:relative_xpath=>'oxns:namePart[@type="given"]'}},
23
- {:institution=>{:relative_xpath=>'oxns:affiliation'}},
24
- {:role=>{:children=>[
25
- {:text=>{:relative_xpath=>'oxns:roleTerm[@type="text"]'}},
26
- {:code=>{:relative_xpath=>'oxns:roleTerm[@type="code"]'}}
27
- ]}}
28
- ]
29
- accessor :organization, :relative_xpath=>'oxns:name[@type="institutional"]', :children=>[
30
- {:role=>{:children=>[
31
- {:text=>{:relative_xpath=>'oxns:roleTerm[@type="text"]'}},
32
- {:code=>{:relative_xpath=>'oxns:roleTerm[@type="code"]'}}
33
- ]}}
34
- ]
35
- accessor :conference, :relative_xpath=>'oxns:name[@type="conference"]', :children=>[
36
- {:role=>{:children=>[
37
- {:text=>{:relative_xpath=>'oxns:roleTerm[@type="text"]'}},
38
- {:code=>{:relative_xpath=>'oxns:roleTerm[@type="code"]'}}
39
- ]}}
40
- ]
41
- accessor :journal, :relative_xpath=>'oxns:relatedItem[@type="host"]', :children=>[
42
- # allows for children that are hashes...
43
- # this allows for more robust handling of nested values (in generating views and when generating solr field names)
44
- {:title=>{:relative_xpath=>'oxns:titleInfo/oxns:title'}},
45
- {:publisher=>{:relative_xpath=>'oxns:originInfo/oxns:publisher'}},
46
- {:issn=>{:relative_xpath=>'oxns:identifier[@type="issn"]'}},
47
- {:date_issued=>{:relative_xpath=>'oxns:originInfo/oxns:dateIssued'}},
48
- {:issue => {:relative_xpath=>"oxns:part", :children=>[
49
- {:volume=>{:relative_xpath=>'oxns:detail[@type="volume"]'}},
50
- {:level=>{:relative_xpath=>'oxns:detail[@type="level"]'}},
51
- {:start_page=>{:relative_xpath=>'oxns:extent[@unit="pages"]/oxns:start'}},
52
- {:end_page=>{:relative_xpath=>'oxns:extent[@unit="pages"]/oxns:end'}},
53
- {:publication_date=>{:relative_xpath=>'oxns:date'}}
54
- ]}}
55
- ]
56
- end
57
-
58
- end
59
-
60
- before(:each) do
61
- article_xml = fixture( File.join("mods_articles", "hydrangea_article1.xml") )
62
- @sample = AccessorTest.from_xml(article_xml)
63
- @sample.stubs(:ox_namespaces).returns("oxns"=>"http://www.loc.gov/mods/v3")
64
- end
65
-
66
- describe '#accessor' do
67
- it "should populate the .accessors hash" do
68
- AccessorTest.accessors[:abstract][:relative_xpath].should == "oxns:abstract"
69
- AccessorTest.accessors[:journal][:relative_xpath].should == 'oxns:relatedItem[@type="host"]'
70
- AccessorTest.accessors[:journal][:children][:issue][:relative_xpath].should == "oxns:part"
71
- AccessorTest.accessors[:journal][:children][:issue][:children][:end_page][:relative_xpath].should == 'oxns:extent[@unit="pages"]/oxns:end'
72
-
73
- AccessorTest.accessors[:person][:children][:role][:children][:text][:relative_xpath].should == 'oxns:roleTerm[@type="text"]'
74
- end
75
- end
76
-
77
- describe ".retrieve" do
78
- it "should use Nokogiri to retrieve a NodeSet corresponding to the combination of accessor keys and array/nodeset indexes" do
79
- @sample.retrieve( :person ).length.should == 2
80
-
81
- @sample.retrieve( {:person=>1} ).first.should == @sample.ng_xml.xpath('//oxns:name[@type="personal"][2]', "oxns"=>"http://www.loc.gov/mods/v3").first
82
- @sample.retrieve( {:person=>1}, :first_name ).class.should == Nokogiri::XML::NodeSet
83
- @sample.retrieve( {:person=>1}, :first_name ).first.text.should == "Siddartha"
84
- end
85
-
86
- it "should support accessors whose relative_xpath is a lookup array instead of an xpath string" do
87
- # pending "this only impacts scenarios where we want to display & edit"
88
- AccessorTest.accessors[:title_info][:children][:language][:relative_xpath].should == {:attribute=>"lang"}
89
- # @sample.retrieve( :title, 1 ).first.text.should == "Artikkelin otsikko Hydrangea artiklan 1"
90
- @sample.retrieve( {:title_info=>1}, :language ).first.text.should == "finnish"
91
- end
92
-
93
- it "should support xpath queries as the pointer" do
94
- @sample.retrieve('//oxns:name[@type="personal"][1]/oxns:namePart[1]').first.text.should == "FAMILY NAME"
95
- end
96
-
97
- it "should return nil if the xpath fails to generate" do
98
- @sample.retrieve( {:foo=>20}, :bar ).should == nil
99
- end
100
-
101
- end
102
-
103
- describe "generated accessor methods" do
104
- it "should mix accessor methods into nodesets so you can use regular array syntax to access stuff" do
105
- pending "This is tempting, but somewhat difficult to implement and potentially slow at runtime. Might never be worth it?"
106
- @sample.persons.length.should == 2
107
- @sample.persons[1].first_name.text.should == "Siddartha"
108
- @sample.persons.last.roles.length.should == 1
109
- @sample.persons.last.roles[0].text.should == "teacher"
110
- end
111
- end
112
-
113
- describe "#accessor_info" do
114
- it "should return the xpath given in the call to #accessor" do
115
- AccessorTest.accessor_info( :abstract ).should == AccessorTest.accessors[:abstract]
116
- end
117
- it "should return the xpath given in the call to #accessor" do
118
- AccessorTest.accessor_info( :abstract ).should == AccessorTest.accessors[:abstract]
119
- end
120
- it "should dig into the accessors hash as far as you want, ignoring index values" do
121
- AccessorTest.accessor_info( *[{:conference=>0}, {:role=>1}, :text] ).should == AccessorTest.accessors[:conference][:children][:role][:children][:text]
122
- AccessorTest.accessor_info( {:conference=>0}, {:role=>1}, :text ).should == AccessorTest.accessors[:conference][:children][:role][:children][:text]
123
-
124
- AccessorTest.accessor_info( :conference, :role, :text ).should == AccessorTest.accessors[:conference][:children][:role][:children][:text]
125
- end
126
- end
127
-
128
- describe "#accessor_xpath" do
129
- it "should return the xpath given in the call to #accessor" do
130
- AccessorTest.accessor_xpath( :abstract ).should == '//oxns:abstract'
131
- end
132
- # Note: Ruby array indexes begin from 0. In xpath queries (which start from 1 instead of 0), this will be translated accordingly.
133
- it "should prepend the xpath for any parent nodes, inserting calls to xpath array lookup where necessary" do
134
- AccessorTest.accessor_xpath( {:conference=>0}, {:role=>1}, :text ).should == '//oxns:name[@type="conference"][1]/oxns:role[2]/oxns:roleTerm[@type="text"]'
135
- end
136
- it "should support xpath queries as argument" do
137
- AccessorTest.accessor_xpath('//oxns:name[@type="personal"][1]/oxns:namePart').should == '//oxns:name[@type="personal"][1]/oxns:namePart'
138
- end
139
- it "should return nil if no accessor_info is available" do
140
- AccessorTest.accessor_xpath( :sample_undeclared_accessor ).should == nil
141
- end
142
- it "should be idempotent" do
143
- AccessorTest.accessor_xpath( *[{:title_info=>2}, :main_title] ).should == "//oxns:titleInfo[3]/oxns:title"
144
- AccessorTest.accessor_xpath( *[{:title_info=>2}, :main_title] ).should == "//oxns:titleInfo[3]/oxns:title"
145
- AccessorTest.accessor_xpath( *[{:title_info=>2}, :main_title] ).should == "//oxns:titleInfo[3]/oxns:title"
146
- end
147
- end
148
-
149
- describe "#accessor_constrained_xpath" do
150
- it 'should append contains("#{constraint_value}") to query' do
151
- # @sample.class.accessor_constrained_xpath_template([:journal, :issn]).should == '//oxns:relatedItem[@type="host"]/oxns:identifier[@type="issn" and contains("#{constraint_value}")]'
152
- @sample.class.accessor_constrained_xpath([:journal, :issn], "123-456-ABC").should == '//oxns:relatedItem[@type="host"]/oxns:identifier[@type="issn" and contains(., "123-456-ABC")]'
153
- @sample.class.accessor_constrained_xpath([:journal, :title], "My Journal Title").should == '//oxns:relatedItem[@type="host"]/oxns:titleInfo/oxns:title[contains(., "My Journal Title")]'
154
- end
155
- end
156
-
157
- describe "#accessor_generic_name" do
158
- it "should generate a generic accessor name based on an array of pointers" do
159
- AccessorTest.accessor_generic_name( {:conference=>0}, {:role=>1}, :text ).should == "conference_role_text"
160
- AccessorTest.accessor_generic_name( *[{:conference=>0}, {:role=>1}, :text] ).should == "conference_role_text"
161
- end
162
- end
163
-
164
- describe "#accessor_hierarchical_name" do
165
- it "should generate a specific accessor name based on an array of pointers and indexes" do
166
- AccessorTest.accessor_hierarchical_name( {:conference=>0}, {:role=>1}, :text ).should == "conference_0_role_1_text"
167
- AccessorTest.accessor_hierarchical_name( *[{:conference=>0}, {:role=>1}, :text] ).should == "conference_0_role_1_text"
168
- end
169
- end
170
-
171
- describe '#generate_accessors_from_properties' do
172
- before(:each) do
173
- class AccessorTest2
174
- include OM::XML::Accessors
175
- end
176
- end
177
-
178
- it "should generate accessors from the properties hash" do
179
- sample_properties_hash = {:abstract=>{:xpath_relative=>"oxns:abstract", :path=>"abstract", :xpath_constrained=>"//oxns:abstract[contains(\\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:abstract", :ref=>:abstract, :convenience_methods=>{}}, :topic_tag=>{:xpath_relative=>"oxns:subject", :path=>"subject", :xpath_constrained=>"//oxns:subject[contains(oxns:topic, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:subject", :ref=>:topic_tag, :default_content_path=>"topic", :convenience_methods=>{}}, :title_info=>{:xpath_relative=>"oxns:titleInfo", :path=>"titleInfo", :xpath_constrained=>"//oxns:titleInfo[contains(\\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:titleInfo", :ref=>:title_info, :convenience_methods=>{:main_title=>{:xpath_relative=>"oxns:title", :path=>"title", :xpath_constrained=>"//oxns:titleInfo[contains(oxns:title, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:titleInfo/oxns:title"}, :language=>{:xpath_relative=>"@lang", :path=>{:attribute=>"lang"}, :xpath_constrained=>"//oxns:titleInfo[contains(@lang, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:titleInfo/@lang"}}}, :person=>{:xpath_relative=>"oxns:name[@type=\"personal\"]", :path=>"name", :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:namePart, \\\"\#{constraint_value}\\\")]", :attributes=>{:type=>"personal"}, :xpath=>"//oxns:name[@type=\"personal\"]", :ref=>:person, :default_content_path=>"namePart", :subelements=>["namePart", "displayForm", "affiliation", :role, "description"], :convenience_methods=>{:first_name=>{:xpath_relative=>"oxns:namePart[@type=\"given\"]", :path=>"namePart", :attributes=>{:type=>"given"}, :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:namePart[@type=\\\"given\\\"], \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name[@type=\"personal\"]/oxns:namePart[@type=\"given\"]"}, :affiliation=>{:xpath_relative=>"oxns:affiliation", :path=>"affiliation", :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:affiliation, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name[@type=\"personal\"]/oxns:affiliation"}, :terms_of_address=>{:xpath_relative=>"oxns:namePart[@type=\"termsOfAddress\"]", :path=>"namePart", :attributes=>{:type=>"termsOfAddress"}, :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:namePart[@type=\\\"termsOfAddress\\\"], \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name[@type=\"personal\"]/oxns:namePart[@type=\"termsOfAddress\"]"}, :namePart=>{:xpath_relative=>"oxns:namePart", :path=>"namePart", :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:namePart, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name[@type=\"personal\"]/oxns:namePart"}, :displayForm=>{:xpath_relative=>"oxns:displayForm", :path=>"displayForm", :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:displayForm, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name[@type=\"personal\"]/oxns:displayForm"}, :role=>{:xpath_relative=>"oxns:role", :path=>"role", :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:role, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name[@type=\"personal\"]/oxns:role", :ref=>:role, :convenience_methods=>{:text=>{:xpath_relative=>"oxns:roleTerm[@type=\"text\"]", :path=>"roleTerm", :attributes=>{:type=>"text"}, :xpath_constrained=>"//oxns:role[contains(oxns:roleTerm[@type=\\\"text\\\"], \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:role/oxns:roleTerm[@type=\"text\"]"}, :code=>{:xpath_relative=>"oxns:roleTerm[@type=\"code\"]", :path=>"roleTerm", :attributes=>{:type=>"code"}, :xpath_constrained=>"//oxns:role[contains(oxns:roleTerm[@type=\\\"code\\\"], \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:role/oxns:roleTerm[@type=\"code\"]"}}, :parents=>[:name_]}, :date=>{:xpath_relative=>"oxns:namePart[@type=\"date\"]", :path=>"namePart", :attributes=>{:type=>"date"}, :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:namePart[@type=\\\"date\\\"], \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name[@type=\"personal\"]/oxns:namePart[@type=\"date\"]"}, :family_name=>{:xpath_relative=>"oxns:namePart[@type=\"family\"]", :path=>"namePart", :attributes=>{:type=>"family"}, :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:namePart[@type=\\\"family\\\"], \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name[@type=\"personal\"]/oxns:namePart[@type=\"family\"]"}, :description=>{:xpath_relative=>"oxns:description", :path=>"description", :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:description, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name[@type=\"personal\"]/oxns:description"}}, :variant_of=>:name_}, :name_=>{:xpath_relative=>"oxns:name", :path=>"name", :xpath_constrained=>"//oxns:name[contains(oxns:namePart, \\\"\#{constraint_value}\\\")]", :attributes=>[:xlink, :lang, "xml:lang", :script, :transliteration, {:type=>["personal", "enumerated", "corporate"]}], :xpath=>"//oxns:name", :ref=>:name_, :default_content_path=>"namePart", :subelements=>["namePart", "displayForm", "affiliation", :role, "description"], :convenience_methods=>{:affiliation=>{:xpath_relative=>"oxns:affiliation", :path=>"affiliation", :xpath_constrained=>"//oxns:name[contains(oxns:affiliation, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name/oxns:affiliation"}, :first_name=>{:xpath_relative=>"oxns:namePart[@type=\"given\"]", :path=>"namePart", :xpath_constrained=>"//oxns:name[contains(oxns:namePart[@type=\\\"given\\\"], \\\"\#{constraint_value}\\\")]", :attributes=>{:type=>"given"}, :xpath=>"//oxns:name/oxns:namePart[@type=\"given\"]"}, :terms_of_address=>{:xpath_relative=>"oxns:namePart[@type=\"termsOfAddress\"]", :path=>"namePart", :xpath_constrained=>"//oxns:name[contains(oxns:namePart[@type=\\\"termsOfAddress\\\"], \\\"\#{constraint_value}\\\")]", :attributes=>{:type=>"termsOfAddress"}, :xpath=>"//oxns:name/oxns:namePart[@type=\"termsOfAddress\"]"}, :displayForm=>{:xpath_relative=>"oxns:displayForm", :path=>"displayForm", :xpath_constrained=>"//oxns:name[contains(oxns:displayForm, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name/oxns:displayForm"}, :namePart=>{:xpath_relative=>"oxns:namePart", :path=>"namePart", :xpath_constrained=>"//oxns:name[contains(oxns:namePart, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name/oxns:namePart"}, :role=>{:xpath_relative=>"oxns:role", :path=>"role", :xpath_constrained=>"//oxns:name[contains(oxns:role, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name/oxns:role", :ref=>:role, :convenience_methods=>{:text=>{:xpath_relative=>"oxns:roleTerm[@type=\"text\"]", :path=>"roleTerm", :attributes=>{:type=>"text"}, :xpath_constrained=>"//oxns:role[contains(oxns:roleTerm[@type=\\\"text\\\"], \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:role/oxns:roleTerm[@type=\"text\"]"}, :code=>{:xpath_relative=>"oxns:roleTerm[@type=\"code\"]", :path=>"roleTerm", :attributes=>{:type=>"code"}, :xpath_constrained=>"//oxns:role[contains(oxns:roleTerm[@type=\\\"code\\\"], \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:role/oxns:roleTerm[@type=\"code\"]"}}, :parents=>[:name_]}, :description=>{:xpath_relative=>"oxns:description", :path=>"description", :xpath_constrained=>"//oxns:name[contains(oxns:description, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name/oxns:description"}, :family_name=>{:xpath_relative=>"oxns:namePart[@type=\"family\"]", :path=>"namePart", :xpath_constrained=>"//oxns:name[contains(oxns:namePart[@type=\\\"family\\\"], \\\"\#{constraint_value}\\\")]", :attributes=>{:type=>"family"}, :xpath=>"//oxns:name/oxns:namePart[@type=\"family\"]"}, :date=>{:xpath_relative=>"oxns:namePart[@type=\"date\"]", :path=>"namePart", :xpath_constrained=>"//oxns:name[contains(oxns:namePart[@type=\\\"date\\\"], \\\"\#{constraint_value}\\\")]", :attributes=>{:type=>"date"}, :xpath=>"//oxns:name/oxns:namePart[@type=\"date\"]"}}}, :role=>{:xpath_relative=>"oxns:role", :path=>"role", :xpath_constrained=>"//oxns:role[contains(\\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:role", :ref=>:role, :convenience_methods=>{:text=>{:xpath_relative=>"oxns:roleTerm[@type=\"text\"]", :path=>"roleTerm", :xpath_constrained=>"//oxns:role[contains(oxns:roleTerm[@type=\\\"text\\\"], \\\"\#{constraint_value}\\\")]", :attributes=>{:type=>"text"}, :xpath=>"//oxns:role/oxns:roleTerm[@type=\"text\"]"}, :code=>{:xpath_relative=>"oxns:roleTerm[@type=\"code\"]", :path=>"roleTerm", :xpath_constrained=>"//oxns:role[contains(oxns:roleTerm[@type=\\\"code\\\"], \\\"\#{constraint_value}\\\")]", :attributes=>{:type=>"code"}, :xpath=>"//oxns:role/oxns:roleTerm[@type=\"code\"]"}}, :parents=>[:name_]}, :unresolved=>{}, :mods=>{:xpath_relative=>"oxns:mods", :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd", :path=>"mods", :xpath_constrained=>"//oxns:mods[contains(\\\"\#{constraint_value}\\\")]", :attributes=>["id", "version"], :xpath=>"//oxns:mods", :ref=>:mods, :convenience_methods=>{}}}
180
- AccessorTest2.stubs(:properties).returns(sample_properties_hash)
181
- AccessorTest2.accessors.should be_nil
182
- AccessorTest2.generate_accessors_from_properties.should_not be_nil
183
- [:mods, :name_, :person, [:person,:first_name],[:person, :role], [:person, :role, :text] ].each do |pointer|
184
- puts pointer
185
- ai = AccessorTest2.accessor_info(*pointer)
186
- ai.should_not be_nil
187
- ai[:relative_xpath].should_not be_nil
188
- end
189
- AccessorTest2.accessor_info(*[:title_info, :language])[:relative_xpath].should == "@lang"
190
- end
191
-
192
- end
193
-
194
- # describe ".accessor_xpath (instance method)" do
195
- # it "should delegate to the class method" do
196
- # AccessorTest.expects(:accessor_xpath).with( [:conference, conference_index, :text_role] )
197
- # @sample.accessor_xpath( [:conference, conference_index, :role] )
198
- # end
199
- # end
200
- #
201
- # describe "generated catchall xpaths" do
202
- # it "should return an xpath query that will catch all nodes corresponding to the specified accessor" do
203
- # AccessorTest.journal_issue_end_page_xpath.should == 'oxns:relatedItem[@type="host"]/oxns:part/oxns:extent[@unit="pages"]/oxns:end'
204
- # end
205
- # it "should rely on #catchall_xpath" do
206
- # AccessorTest.expects(:catchall_xpath).with(:journal, :issue, :end_page)
207
- # AccessorTest.journal_issue_end_page_xpath
208
- # end
209
- # end
210
- #
211
- # describe ".catchall_xpath" do
212
- # it "should return an xpath query that will catch all nodes corresponding to the specified accessor" do
213
- # AccessorTest.catchall_xpath(:journal, :issue, :end_page).should == 'oxns:relatedItem[@type="host"]/oxns:part/oxns:extent[@unit="pages"]/oxns:end'
214
- # end
215
- # end
216
- end
@@ -1,67 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
- require "om"
3
-
4
- describe "OM::XML::Generator" do
5
-
6
- before(:all) do
7
- #ModsHelpers.name_("Beethoven, Ludwig van", :date=>"1770-1827", :role=>"creator")
8
- class GeneratorTest
9
-
10
- include OM::XML::Container
11
- include OM::XML::Properties
12
- include OM::XML::Generator
13
-
14
- # Could add support for multiple root declarations.
15
- # For now, assume that any modsCollections have already been broken up and fed in as individual mods documents
16
- # root :mods_collection, :path=>"modsCollection",
17
- # :attributes=>[],
18
- # :subelements => :mods
19
-
20
- root_property :mods, "mods", "http://www.loc.gov/mods/v3", :attributes=>["id", "version"], :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd"
21
-
22
-
23
- property :name_, :path=>"name",
24
- :attributes=>[:xlink, :lang, "xml:lang", :script, :transliteration, {:type=>["personal", "enumerated", "corporate"]} ],
25
- :subelements=>["namePart", "displayForm", "affiliation", :role, "description"],
26
- :default_content_path => "namePart",
27
- :convenience_methods => {
28
- :date => {:path=>"namePart", :attributes=>{:type=>"date"}},
29
- :family_name => {:path=>"namePart", :attributes=>{:type=>"family"}},
30
- :given_name => {:path=>"namePart", :attributes=>{:type=>"given"}},
31
- :terms_of_address => {:path=>"namePart", :attributes=>{:type=>"termsOfAddress"}}
32
- }
33
- property :person, :variant_of=>:name_, :attributes=>{:type=>"personal"}
34
- property :role, :path=>"role",
35
- :parents=>[:name_],
36
- :attributes=>[ { "type"=>["text", "code"] } , "authority"],
37
- :default_content_path => "roleTerm"
38
-
39
- end
40
-
41
- end
42
-
43
- before(:each) do
44
- @sample = GeneratorTest.from_xml( fixture( File.join("test_dummy_mods.xml") ) )
45
- end
46
-
47
- after(:all) do
48
- Object.send(:remove_const, :GeneratorTest)
49
- end
50
-
51
- describe '#generate' do
52
- it "should use the corresponding builder template(s) to generate the node" do
53
- GeneratorTest.generate(:mods, "foo").root.to_xml.should == "<mods>foo</mods>"
54
- # GeneratorTest.generate([:person,:role], "creator", {:attributes=>{"type"=>"code", "authority"=>"marcrelator"}}).root.to_xml.should == "<role authority=\"marcrelator\" type=\"code\">\n <roleTerm>creator</roleTerm>\n</role>"
55
- generated_node = GeneratorTest.generate([:person,:role], "creator", {:attributes=>{"type"=>"code", "authority"=>"marcrelator"}})
56
- # generated_node.should have_node 'role[@authority="marcrelator"][@type="code"]' do
57
- # with_node "roleTerm", "creator"
58
- # end
59
- generated_node.xpath('./role[@authority="marcrelator"][@type="code"]').xpath("./roleTerm").text.should == "creator"
60
-
61
- end
62
- it "should return Nokogiri Documents" do
63
- GeneratorTest.generate(:mods, "foo").class.should == Nokogiri::XML::Document
64
- end
65
- end
66
-
67
- end
@@ -1,315 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
- require "om"
3
-
4
- describe "OM::XML::Properties" do
5
-
6
- before(:all) do
7
- #ModsHelpers.name_("Beethoven, Ludwig van", :date=>"1770-1827", :role=>"creator")
8
- class FakeOxMods
9
-
10
- include OM::XML::Container
11
- include OM::XML::Properties
12
-
13
- # Could add support for multiple root declarations.
14
- # For now, assume that any modsCollections have already been broken up and fed in as individual mods documents
15
- # root :mods_collection, :path=>"modsCollection",
16
- # :attributes=>[],
17
- # :subelements => :mods
18
-
19
-
20
- root_property :mods, "mods", "http://www.loc.gov/mods/v3", :attributes=>["id", "version"], :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd"
21
-
22
- property :title_info, :path=>"titleInfo",
23
- :convenience_methods => {
24
- :main_title => {:path=>"title"},
25
- :language => {:path=>{:attribute=>"lang"}},
26
- }
27
-
28
- property :name_, :path=>"name",
29
- :attributes=>[:xlink, :lang, "xml:lang", :script, :transliteration, {:type=>["personal", "enumerated", "corporate"]} ],
30
- :subelements=>["namePart", "displayForm", "affiliation", :role, "description"],
31
- :default_content_path => "namePart",
32
- :convenience_methods => {
33
- :date => {:path=>"namePart", :attributes=>{:type=>"date"}},
34
- :family_name => {:path=>"namePart", :attributes=>{:type=>"family"}},
35
- :given_name => {:path=>"namePart", :attributes=>{:type=>"given"}},
36
- :terms_of_address => {:path=>"namePart", :attributes=>{:type=>"termsOfAddress"}}
37
- }
38
-
39
- property :person, :variant_of=>:name_, :attributes=>{:type=>"personal"}
40
-
41
- property :role, :path=>"role",
42
- :parents=>[:name_],
43
- :attributes=>[ { "type"=>["text", "code"] } , "authority"],
44
- :default_content_path => "roleTerm"
45
-
46
- property :journal, :path=>'relatedItem', :attributes=>{:type=>"host"},
47
- :subelements=>[:title_info, :origin_info, :issue],
48
- :convenience_methods => {
49
- :issn => {:path=>"identifier", :attributes=>{:type=>"issn"}},
50
- }
51
-
52
- property :issue, :path=>'part',
53
- :subelements=>[:start_page, :end_page, :volume],
54
- :convenience_methods => {
55
- # :volume => {:path=>"detail", :attributes=>{:type=>"volume"}},
56
- :level => {:path=>"detail", :attributes=>{:type=>"number"}, :default_content_path=>"number"},
57
- # Hack to support provisional spot for start & end page (nesting was too deep for this version of OM)
58
- :citation_start_page => {:path=>"pages", :attributes=>{:type=>"start"}},
59
- :citation_end_page => {:path=>"pages", :attributes=>{:type=>"end"}},
60
- :foo => {:path=>"foo", :attributes=>{:type=>"ness"}},
61
- :publication_date => {:path=>"date"}
62
- }
63
-
64
- property :volume, :path=>"detail", :attributes=>{:type=>"volume"}, :subelements=>"number"
65
-
66
- property :start_page, :path=>"extent", :attributes=>{:unit=>"pages"}, :default_content_path => "start"
67
- property :end_page, :path=>"extent", :attributes=>{:unit=>"pages"}, :default_content_path => "end"
68
- end
69
-
70
- class FakeOtherOx < Nokogiri::XML::Document
71
-
72
- include OM::XML::Properties
73
- # extend OX::ClassMethods
74
-
75
- root_property :other, "other", "http://www.foo.com"
76
-
77
- end
78
-
79
- end
80
-
81
- before(:each) do
82
- @fixturemods = FakeOxMods.from_xml( fixture( File.join("CBF_MODS", "ARS0025_016.xml") ) )
83
- end
84
-
85
- after(:all) do
86
- Object.send(:remove_const, :FakeOxMods)
87
- end
88
-
89
- describe "#new" do
90
- it "should set up namespaces" do
91
- @fixturemods.ox_namespaces.should == {"oxns"=>"http://www.loc.gov/mods/v3", "xmlns:ns2"=>"http://www.w3.org/1999/xlink", "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance", "xmlns:ns3"=>"http://www.loc.gov/mods/v3"}
92
- end
93
- end
94
-
95
- describe "#root_property" do
96
- it "should initialize root_property class attributes without attributes bleeding over to other OX classes" do
97
- FakeOxMods.root_property_ref.should == :mods
98
- FakeOxMods.root_config.should == {:ref=>:mods, :path=>"mods", :namespace=>"http://www.loc.gov/mods/v3", :attributes=>["id", "version"], :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd"}
99
- FakeOxMods.ox_namespaces.should == {"oxns"=>"http://www.loc.gov/mods/v3"}
100
-
101
- FakeOtherOx.root_property_ref.should == :other
102
- FakeOtherOx.root_config.should == {:namespace=>"http://www.foo.com", :path=>"other", :ref=>:other}
103
- end
104
- it "should add a corresponding entry into the properties hash" do
105
- FakeOxMods.property_info_for(FakeOxMods.root_property_ref).should == {:schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd", :xpath_relative=>"oxns:mods", :path=>"mods", :xpath_constrained=>"//oxns:mods[contains(\\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:mods", :ref=>:mods, :convenience_methods=>{}, :attributes=>["id", "version"]}
106
- FakeOxMods.builder_template(FakeOxMods.root_property_ref).should == "xml.mods( '\#{builder_new_value}' )"
107
- end
108
- end
109
-
110
- describe "#property" do
111
-
112
- it "fails gracefully if you try to look up nodes for an undefined property" do
113
- @fixturemods.lookup(:nobody_home).should == []
114
- end
115
-
116
- it "constructs xpath queries for finding properties" do
117
- FakeOxMods.properties[:name_][:xpath].should == '//oxns:name'
118
- FakeOxMods.properties[:name_][:xpath_relative].should == 'oxns:name'
119
-
120
- FakeOxMods.properties[:person][:xpath].should == '//oxns:name[@type="personal"]'
121
- FakeOxMods.properties[:person][:xpath_relative].should == 'oxns:name[@type="personal"]'
122
- end
123
-
124
- it "constructs templates for value-driven searches" do
125
- FakeOxMods.properties[:name_][:xpath_constrained].should == '//oxns:name[contains(oxns:namePart, "#{constraint_value}")]'.gsub('"', '\"')
126
- FakeOxMods.properties[:person][:xpath_constrained].should == '//oxns:name[@type="personal" and contains(oxns:namePart, "#{constraint_value}")]'.gsub('"', '\"')
127
-
128
- # Example of how you could use these templates:
129
- constraint_value = "SAMPLE CONSTRAINT VALUE"
130
- constrained_query = eval( '"' + FakeOxMods.properties[:person][:xpath_constrained] + '"' )
131
- constrained_query.should == '//oxns:name[@type="personal" and contains(oxns:namePart, "SAMPLE CONSTRAINT VALUE")]'
132
- end
133
-
134
- it "constructs xpath queries & templates for convenience methods" do
135
- FakeOxMods.properties[:name_][:convenience_methods][:date][:xpath].should == '//oxns:name/oxns:namePart[@type="date"]'
136
- FakeOxMods.properties[:name_][:convenience_methods][:date][:xpath_relative].should == 'oxns:namePart[@type="date"]'
137
- FakeOxMods.properties[:name_][:convenience_methods][:date][:xpath_constrained].should == '//oxns:name[contains(oxns:namePart[@type="date"], "#{constraint_value}")]'.gsub('"', '\"')
138
-
139
- FakeOxMods.properties[:person][:convenience_methods][:date][:xpath].should == '//oxns:name[@type="personal"]/oxns:namePart[@type="date"]'
140
- FakeOxMods.properties[:person][:convenience_methods][:date][:xpath_relative].should == 'oxns:namePart[@type="date"]'
141
- FakeOxMods.properties[:person][:convenience_methods][:date][:xpath_constrained].should == '//oxns:name[@type="personal" and contains(oxns:namePart[@type="date"], "#{constraint_value}")]'.gsub('"', '\"')
142
-
143
- end
144
-
145
- it "constructs xpath queries & templates for subelements too" do
146
- FakeOxMods.properties[:person][:convenience_methods][:displayForm][:xpath].should == '//oxns:name[@type="personal"]/oxns:displayForm'
147
- FakeOxMods.properties[:person][:convenience_methods][:displayForm][:xpath_relative].should == 'oxns:displayForm'
148
- FakeOxMods.properties[:person][:convenience_methods][:displayForm][:xpath_constrained].should == '//oxns:name[@type="personal" and contains(oxns:displayForm, "#{constraint_value}")]'.gsub('"', '\"')
149
- end
150
-
151
- it "supports subelements that are specified as separate properties" do
152
- FakeOxMods.properties[:name_][:convenience_methods][:role][:xpath].should == '//oxns:name/oxns:role'
153
- FakeOxMods.properties[:name_][:convenience_methods][:role][:xpath_relative].should == 'oxns:role'
154
- FakeOxMods.properties[:name_][:convenience_methods][:role][:xpath_constrained].should == '//oxns:name[contains(oxns:role/oxns:roleTerm, "#{constraint_value}")]'.gsub('"', '\"')
155
- end
156
-
157
- it "supports treating attributes as properties" do
158
- FakeOxMods.properties[:title_info][:convenience_methods][:language][:xpath].should == '//oxns:titleInfo/@lang'
159
- FakeOxMods.properties[:title_info][:convenience_methods][:language][:xpath_relative].should == '@lang'
160
- FakeOxMods.properties[:title_info][:convenience_methods][:language][:xpath_constrained].should == '//oxns:titleInfo[contains(@lang, "#{constraint_value}")]'.gsub('"', '\"')
161
- end
162
-
163
- it "should support deep nesting of properties" do
164
- pending "requires property method to be recursive"
165
-
166
- FakeOxMods.properties[:journal][:convenience_methods][:issue][:convenience_methods][:volume].should == {:xpath_constrained=>"//oxns:part[contains(oxns:detail[@type=\\\"volume\\\"], \\\"\#{constraint_value}\\\")]", :path=>"detail", :attributes=>{:type=>"volume"}, :xpath=>"//oxns:part/oxns:detail[@type=\"volume\"]", :xpath_relative=>"oxns:detail[@type=\"volume\"]"}
167
- prop_info = FakeOxMods.property_info_for([:journal, :issue, :volume])
168
- prop_info[:xpath_constrained].should == "//oxns:part[contains(oxns:detail[@type=\\\"volume\\\"], \\\"\#{constraint_value}\\\")]"
169
- prop_info[:xpath].should == "//oxns:part/oxns:detail[@type=\"volume\"]"
170
- prop_info[:xpath_relative].should == "oxns:detail[@type=\"volume\"]"
171
- end
172
-
173
- it "should support even deeper nesting of properties" do
174
- pending "requires property method to be recursive"
175
-
176
- FakeOxMods.properties[:journal][:convenience_methods][:issue][:convenience_methods][:start_page].should == {:xpath_constrained=>"//oxns:part[contains(oxns:detail[@type=\\\"volume\\\"], \\\"\#{constraint_value}\\\")]", :path=>"detail", :attributes=>{:type=>"volume"}, :xpath=>"//oxns:part/oxns:detail[@type=\"volume\"]", :xpath_relative=>"oxns:detail[@type=\"volume\"]"}
177
- FakeOxMods.property_info_for([:journal, :issue, :end_page]).should == ""
178
- end
179
-
180
- it "should not overwrite default property info when adding a variant property" do
181
- FakeOxMods.properties[:name_].should_not equal(FakeOxMods.properties[:person])
182
- FakeOxMods.properties[:name_][:convenience_methods].should_not equal(FakeOxMods.properties[:person][:convenience_methods])
183
-
184
- FakeOxMods.properties[:name_][:xpath].should_not == FakeOxMods.properties[:person][:xpath]
185
- FakeOxMods.properties[:name_][:convenience_methods][:date][:xpath_constrained].should_not == FakeOxMods.properties[:person][:convenience_methods][:date][:xpath_constrained]
186
- end
187
-
188
- end
189
-
190
- describe ".lookup" do
191
-
192
- it "uses the generated xpath queries" do
193
- @fixturemods.ng_xml.expects(:xpath).with('//oxns:name[@type="personal"]', @fixturemods.ox_namespaces)
194
- @fixturemods.lookup(:person)
195
-
196
- @fixturemods.ng_xml.expects(:xpath).with('//oxns:name[@type="personal" and contains(oxns:namePart, "Beethoven, Ludwig van")]', @fixturemods.ox_namespaces)
197
- @fixturemods.lookup(:person, "Beethoven, Ludwig van")
198
-
199
- @fixturemods.ng_xml.expects(:xpath).with('//oxns:name[@type="personal" and contains(oxns:namePart[@type="date"], "2010")]', @fixturemods.ox_namespaces)
200
- @fixturemods.lookup(:person, :date=>"2010")
201
-
202
- @fixturemods.ng_xml.expects(:xpath).with('//oxns:name[@type="personal" and contains(oxns:role/oxns:roleTerm, "donor")]', @fixturemods.ox_namespaces)
203
- @fixturemods.lookup(:person, :role=>"donor")
204
-
205
- #
206
- # This is the way we want to move towards... (currently implementing part of this in accessor_constrained_xpath)
207
- # @fixturemods.ng_xml.expects(:xpath).with('//oxns:relatedItem/oxns:identifier[@type=\'issn\'] and contains("123-ABC-44567")]', @fixturemods.ox_namespaces)
208
- # @fixturemods.lookup([:journal, :issn], "123-ABC-44567")
209
-
210
- end
211
-
212
- end
213
-
214
- describe ".xpath_query_for" do
215
-
216
- it "retrieves the generated xpath query to match your desires" do
217
- @fixturemods.xpath_query_for(:person).should == '//oxns:name[@type="personal"]'
218
-
219
- @fixturemods.xpath_query_for(:person, "Beethoven, Ludwig van").should == '//oxns:name[@type="personal" and contains(oxns:namePart, "Beethoven, Ludwig van")]'
220
-
221
- @fixturemods.xpath_query_for(:person, :date=>"2010").should == '//oxns:name[@type="personal" and contains(oxns:namePart[@type="date"], "2010")]'
222
-
223
- @fixturemods.xpath_query_for(:person, :role=>"donor").should == '//oxns:name[@type="personal" and contains(oxns:role/oxns:roleTerm, "donor")]'
224
-
225
- @fixturemods.xpath_query_for([:person,:date]).should == '//oxns:name[@type="personal"]/oxns:namePart[@type="date"]'
226
-
227
- @fixturemods.xpath_query_for([:person,:date], "2010").should == '//oxns:name[@type="personal" and contains(oxns:namePart[@type="date"], "2010")]'
228
- end
229
-
230
- it "parrots any strings back to you (in case you already have an xpath query)" do
231
- @fixturemods.xpath_query_for('//oxns:name[@type="personal"]/oxns:namePart[@type="date"]').should == '//oxns:name[@type="personal"]/oxns:namePart[@type="date"]'
232
- end
233
-
234
- end
235
-
236
- describe "#generate_xpath" do
237
- it "should generate an xpath query from the options in the provided hash and should support generating xpaths with constraint values" do
238
- opts1 = {:path=>"name", :default_content_path=>"namePart"}
239
- opts2 = {:path=>"originInfo"}
240
- opts3 = {:path=>["name", "namePart"]}
241
- FakeOxMods.generate_xpath( opts1 ).should == '//oxns:name'
242
- FakeOxMods.generate_xpath( opts1, :constraints=>:default ).should == '//oxns:name[contains(oxns:namePart, "#{constraint_value}")]'
243
- FakeOxMods.generate_xpath( opts2, :constraints=>:default ).should == '//oxns:originInfo[contains("#{constraint_value}")]'
244
-
245
- FakeOxMods.generate_xpath( opts1, :variations=>{:attributes=>{:type=>"personal"}} ).should == '//oxns:name[@type="personal"]'
246
- FakeOxMods.generate_xpath( opts1, :variations=>{:attributes=>{:type=>"personal"}}, :constraints=>:default ).should == '//oxns:name[@type="personal" and contains(oxns:namePart, "#{constraint_value}")]'
247
-
248
- FakeOxMods.generate_xpath( opts1, :constraints=>{:path=>"namePart", :attributes=>{:type=>"date"}} ).should == '//oxns:name[contains(oxns:namePart[@type="date"], "#{constraint_value}")]'
249
- FakeOxMods.generate_xpath( opts1, :constraints=>{:path=>"namePart", :attributes=>{:type=>"date"}}, :variations=>{:attributes=>{:type=>"personal"}} ).should == '//oxns:name[@type="personal" and contains(oxns:namePart[@type="date"], "#{constraint_value}")]'
250
- FakeOxMods.generate_xpath(FakeOxMods.properties[:person], :variations=>{:attributes=>{:type=>"personal"}}, :constraints=>{:path=>"role", :default_content_path=>"roleTerm"}, :subelement_of=>":person").should == '//oxns:name[@type="personal" and contains(oxns:role/oxns:roleTerm, "#{constraint_value}")]'
251
-
252
- FakeOxMods.generate_xpath(opts1, :variations=>{:attributes=>{:type=>"personal"}, :subelement_path=>"displayForm" } ).should == '//oxns:name[@type="personal"]/oxns:displayForm'
253
- FakeOxMods.generate_xpath(opts1, :variations=>{:attributes=>{:type=>"personal"}}, :constraints=>{:path=>"displayForm"} ).should == '//oxns:name[@type="personal" and contains(oxns:displayForm, "#{constraint_value}")]'
254
- FakeOxMods.generate_xpath(opts1, :variations=>{:attributes=>{:type=>"personal"}, :subelement_path=>["role", "roleTerm"] } ).should == '//oxns:name[@type="personal"]/oxns:role/oxns:roleTerm'
255
-
256
- FakeOxMods.generate_xpath( opts3, :variations=>{:attributes=>{:type=>"date"}} ).should == '//oxns:name/oxns:namePart[@type="date"]'
257
- FakeOxMods.generate_xpath( opts3, :variations=>{:attributes=>{:type=>"date"}}, :constraints=>:default ).should == '//oxns:name/oxns:namePart[@type="date" and contains("#{constraint_value}")]'
258
-
259
- FakeOxMods.generate_xpath( {:path=>["relatedItem", "identifier"]}, :variations=>{:attributes=>{:type=>"issn"}}, :constraints=>:default ).should == '//oxns:relatedItem/oxns:identifier[@type="issn" and contains("#{constraint_value}")]'
260
-
261
- end
262
-
263
-
264
- it "should support relative paths" do
265
- relative_opts = {:path=>"namePart"}
266
- FakeOxMods.generate_xpath( relative_opts, :variations=>{:attributes=>{:type=>"date"}}, :relative=>true).should == 'oxns:namePart[@type="date"]'
267
- end
268
-
269
- it "should work with real properties hashes" do
270
- FakeOxMods.generate_xpath(FakeOxMods.properties[:person], :variations=>FakeOxMods.properties[:person]).should == "//oxns:name[@type=\"personal\"]"
271
- FakeOxMods.generate_xpath(FakeOxMods.properties[:person], :variations=>FakeOxMods.properties[:person], :constraints=>{:path=>"role", :default_content_path=>"roleTerm"}, :subelement_of=>":person").should == '//oxns:name[@type="personal" and contains(oxns:role/oxns:roleTerm, "#{constraint_value}")]'
272
- date_hash = FakeOxMods.properties[:person][:convenience_methods][:date]
273
- FakeOxMods.generate_xpath( date_hash, :variations=>date_hash, :relative=>true ).should == 'oxns:namePart[@type="date"]'
274
- end
275
-
276
- it "should support custom templates" do
277
- opts = {:path=>"name", :default_content_path=>"namePart"}
278
- FakeOxMods.generate_xpath( opts, :template=>'/#{prefix}:sampleNode/#{prefix}:#{path}[contains(#{default_content_path}, \":::constraint_value:::\")]' ).should == '/oxns:sampleNode/oxns:name[contains(namePart, "#{constraint_value}")]'
279
- end
280
- end
281
-
282
- describe "#builder_template" do
283
-
284
- it "should generate a template call for passing into the builder block (assumes 'xml' as the argument for the block)" do
285
- FakeOxMods.builder_template([:person,:date]).should == 'xml.namePart( \'#{builder_new_value}\', :type=>\'date\' )'
286
- FakeOxMods.builder_template([:name_,:affiliation]).should == 'xml.affiliation( \'#{builder_new_value}\' )'
287
-
288
- simple_role_builder_template = 'xml.role( :type=>\'text\' ) { xml.roleTerm( \'#{builder_new_value}\' ) }'
289
- FakeOxMods.builder_template([:role]).should == simple_role_builder_template
290
- FakeOxMods.builder_template([:person,:role]).should == simple_role_builder_template
291
-
292
- marcrelator_role_builder_template = 'xml.role( :type=>\'code\', :authority=>\'marcrelator\' ) { xml.roleTerm( \'#{builder_new_value}\' ) }'
293
- FakeOxMods.builder_template([:role], {:attributes=>{"type"=>"code", "authority"=>"marcrelator"}} ).should == marcrelator_role_builder_template
294
- FakeOxMods.builder_template([:person,:role], {:attributes=>{"type"=>"code", "authority"=>"marcrelator"}} ).should == marcrelator_role_builder_template
295
- end
296
-
297
- it "should work with deeply nested properties" do
298
- FakeOxMods.builder_template([:issue, :volume]).should == "xml.detail( '\#{builder_new_value}', :type=>'volume' )"
299
- FakeOxMods.builder_template([:volume, :number]).should == "xml.number( '\#{builder_new_value}' )"
300
- FakeOxMods.builder_template([:journal, :issue, :level]).should == "xml.detail( :type=>'number' ) { xml.number( '\#{builder_new_value}' ) }"
301
- FakeOxMods.builder_template([:journal, :issue, :volume]).should == "xml.detail( '\#{builder_new_value}', :type=>'volume' )"
302
- FakeOxMods.builder_template([:journal, :issue, :volume, :number]).should == "xml.number( '\#{builder_new_value}' )"
303
- FakeOxMods.builder_template([:journal, :issue, :start_page]).should == "xml.extent( :unit=>'pages' ) { xml.start( '\#{builder_new_value}' ) }"
304
- end
305
-
306
- end
307
-
308
- describe "#applicable_attributes" do
309
- it "returns a Hash where all of the values are strings" do
310
- FakeOxMods.send(:applicable_attributes, {:type=>"date"} ).should == {:type=>"date"}
311
- FakeOxMods.send(:applicable_attributes, ["authority", {:type=>["text","code"]}] ).should == {:type=>"text"}
312
- end
313
- end
314
-
315
- end