om 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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