om 1.6.0 → 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/COMMON_OM_PATTERNS.textile +13 -1
  2. data/Gemfile +7 -4
  3. data/Gemfile.lock +19 -14
  4. data/History.textile +4 -0
  5. data/lib/om/version.rb +1 -1
  6. data/lib/om/xml/document.rb +16 -2
  7. data/lib/om/xml/terminology.rb +5 -0
  8. data/lib/tasks/om.rake +16 -10
  9. data/om.gemspec +1 -0
  10. data/spec/fixtures/mods_articles/hydrangea_article1.xml +7 -0
  11. data/spec/integration/differentiated_elements_spec.rb +39 -0
  12. data/spec/integration/element_value_spec.rb +91 -0
  13. data/spec/integration/proxies_and_ref_spec.rb +81 -0
  14. data/spec/integration/querying_documents_spec.rb +73 -0
  15. data/spec/integration/rights_metadata_integration_example_spec.rb +2 -4
  16. data/spec/integration/selective_querying_spec.rb +89 -0
  17. data/spec/integration/set_reentrant_terminology_spec.rb +134 -0
  18. data/spec/integration/xpathy_stuff_spec.rb +204 -0
  19. data/spec/spec_helper.rb +8 -0
  20. data/spec/unit/container_spec.rb +2 -4
  21. data/spec/unit/document_spec.rb +2 -3
  22. data/spec/unit/dynamic_node_spec.rb +1 -2
  23. data/spec/unit/named_term_proxy_spec.rb +1 -2
  24. data/spec/unit/node_generator_spec.rb +2 -3
  25. data/spec/unit/nokogiri_sanity_spec.rb +2 -3
  26. data/spec/unit/om_spec.rb +2 -4
  27. data/spec/unit/template_registry_spec.rb +1 -2
  28. data/spec/unit/term_builder_spec.rb +2 -3
  29. data/spec/unit/term_spec.rb +1 -2
  30. data/spec/unit/term_value_operators_spec.rb +2 -3
  31. data/spec/unit/term_xpath_generator_spec.rb +1 -2
  32. data/spec/unit/terminology_builder_spec.rb +1 -2
  33. data/spec/unit/terminology_spec.rb +1 -2
  34. data/spec/unit/validation_spec.rb +2 -4
  35. data/spec/unit/xml_serialization_spec.rb +2 -4
  36. data/spec/unit/xml_spec.rb +2 -4
  37. metadata +68 -13
@@ -1,6 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
- require "nokogiri"
3
- require "om"
1
+ require 'spec_helper'
4
2
 
5
3
  describe "OM::XML::Accessors" do
6
4
 
@@ -75,4 +73,4 @@ describe "OM::XML::Accessors" do
75
73
  end
76
74
  end
77
75
 
78
- end
76
+ end
@@ -0,0 +1,89 @@
1
+ # These tests illustrate how to select nodes based on their position
2
+ # within an XML hierarchy and the value of particular attributes.
3
+
4
+ require 'spec_helper'
5
+
6
+ describe "Selecting nodes based on (a) position in hierarchy and (b) attributes" do
7
+
8
+ before(:all) do
9
+
10
+ # Some XML, with various flavors of <note> nodes:
11
+ # - outer vs inner;
12
+ # - with vs without an "a" attribute.
13
+ @xml = %Q{
14
+ <root xmlns="foo">
15
+ <note>o1</note>
16
+ <note>o2</note>
17
+ <note a="a">o3a</note>
18
+ <note a="a">o4a</note>
19
+ <inner>
20
+ <note>i1</note>
21
+ <note>i2</note>
22
+ <note a="a">i3a</note>
23
+ <note a="a">i4a</note>
24
+ </inner>
25
+ </root>
26
+ }
27
+
28
+ # Our document class and its OM terminology.
29
+ #
30
+ # In order to select only the outer or inner <note> nodes, we must use
31
+ # the :proxy approach shown below; however, that approach does not work
32
+ # with :attributes. Thus, the general strategy here is first to define OM
33
+ # terms for any attibute-based selections we might want, and then to
34
+ # refine those further using :proxy.
35
+ class FooDoc
36
+ include OM::XML::Document
37
+
38
+ set_terminology do |t|
39
+ t.root :path => 'root', :xmlns => 'foo'
40
+
41
+ # All notes.
42
+ t.note
43
+ t.all_note :path => 'note' # Included for symmetry.
44
+
45
+ # All notes with and without attributes.
46
+ t.all_note_a :path => 'note', :attributes => { :a => "a" }
47
+ t.all_note_not_a :path => 'note', :attributes => { :a => :none }
48
+
49
+ # All inner notes -- again, with and without attributes.
50
+ t.inner do
51
+ t.note
52
+ t.note_a :path => 'note', :attributes => { :a => "a" }
53
+ t.note_not_a :path => 'note', :attributes => { :a => :none }
54
+ end
55
+
56
+ # Using the terms defined above, we can now define any additional
57
+ # selections we might need.
58
+ t.all_outer_note :proxy => [:root, :note]
59
+ t.all_inner_note :proxy => [:root, :inner, :note]
60
+ t.outer_note_a :proxy => [:root, :all_note_a]
61
+ t.outer_note_not_a :proxy => [:root, :all_note_not_a]
62
+ t.inner_note_a :proxy => [:root, :inner, :note_a]
63
+ t.inner_note_not_a :proxy => [:root, :inner, :note_not_a]
64
+ end
65
+ end
66
+
67
+ # A document instance.
68
+ @doc = FooDoc.from_xml(@xml)
69
+ end
70
+
71
+
72
+ # Did it work?
73
+ it "should be able to select all types of <note> nodes" do
74
+ tests = [
75
+ # OM term. Expected result.
76
+ [ 'all_note', %w(o1 o2 o3a o4a i1 i2 i3a i4a) ],
77
+ [ 'all_note_a', %w( o3a o4a i3a i4a) ],
78
+ [ 'all_note_not_a', %w(o1 o2 i1 i2 ) ],
79
+ [ 'all_outer_note', %w(o1 o2 o3a o4a ) ],
80
+ [ 'all_inner_note', %w( i1 i2 i3a i4a) ],
81
+ [ 'outer_note_a', %w( o3a o4a ) ],
82
+ [ 'outer_note_not_a', %w(o1 o2 ) ],
83
+ [ 'inner_note_a', %w( i3a i4a) ],
84
+ [ 'inner_note_not_a', %w( i1 i2 ) ],
85
+ ]
86
+ tests.each { |meth, exp| @doc.send(meth).should == exp }
87
+ end
88
+
89
+ end
@@ -0,0 +1,134 @@
1
+ require 'spec_helper'
2
+
3
+ describe "calling set_terminology more than once" do
4
+
5
+ before(:all) do
6
+ class ReentrantTerminology
7
+ include OM::XML::Document
8
+
9
+ set_terminology do |t|
10
+ t.root :path => 'root', :xmlns => "asdf"
11
+ t.foo
12
+ end
13
+ end
14
+ end
15
+
16
+ describe "before" do
17
+
18
+ subject do
19
+ xml = '<root xmlns="asdf"><foo>fooval</foo><bar>barval</bar></root>'
20
+ ReentrantTerminology.from_xml(xml)
21
+ end
22
+
23
+ it "can get foo" do
24
+ subject.foo.should == ['fooval']
25
+ end
26
+
27
+ it "cannot get bar" do
28
+ expect { subject.bar }.to raise_error OM::XML::Terminology::BadPointerError
29
+ end
30
+
31
+ end
32
+
33
+ describe "after" do
34
+
35
+ before(:all) do
36
+ class ReentrantTerminology
37
+ set_terminology do |t|
38
+ t.root :path => 'root', :xmlns => "asdf"
39
+ t.bar
40
+ end
41
+ end
42
+ end
43
+
44
+ subject do
45
+ xml = '<root xmlns="asdf"><foo>fooval</foo><bar>barval</bar></root>'
46
+ ReentrantTerminology.from_xml(xml)
47
+ end
48
+
49
+ it "cannot get foo" do
50
+ expect { subject.foo }.to raise_error OM::XML::Terminology::BadPointerError
51
+ end
52
+
53
+ it "can now get bar" do
54
+ subject.bar.should == ['barval']
55
+ end
56
+
57
+ end
58
+
59
+ describe "re-entrant modification" do
60
+
61
+
62
+ before(:all) do
63
+ class ReentrantTerminology
64
+ set_terminology do |t|
65
+ t.root :path => 'root', :xmlns => "asdf"
66
+ t.foo
67
+ end
68
+ end
69
+
70
+ class ReentrantTerminology
71
+ extend_terminology do |t|
72
+ t.bar
73
+ end
74
+ end
75
+ end
76
+
77
+ subject do
78
+ xml = '<root xmlns="asdf"><foo>fooval</foo><bar>barval</bar></root>'
79
+ ReentrantTerminology.from_xml(xml)
80
+ end
81
+
82
+ it "can get foo" do
83
+ subject.foo.should == ['fooval']
84
+ end
85
+
86
+ it "can get bar" do
87
+ subject.bar.should == ['barval']
88
+ end
89
+
90
+ end
91
+
92
+ describe "subclass modification" do
93
+
94
+
95
+ before(:all) do
96
+ class ReentrantTerminology
97
+ set_terminology do |t|
98
+ t.root :path => 'root', :xmlns => "asdf"
99
+ t.foo
100
+ end
101
+ end
102
+
103
+ class LocalReentrantTerminology
104
+ include OM::XML::Document
105
+ use_terminology(ReentrantTerminology)
106
+ extend_terminology do |t|
107
+ t.bar
108
+ end
109
+ end
110
+ end
111
+
112
+ subject do
113
+ xml = '<root xmlns="asdf"><foo>fooval</foo><bar>barval</bar></root>'
114
+ LocalReentrantTerminology.from_xml(xml)
115
+ end
116
+
117
+ it "shouldn't bleed up the inheritence stack" do
118
+ xml = '<root xmlns="asdf"><foo>fooval</foo><bar>barval</bar></root>'
119
+ t = ReentrantTerminology.from_xml(xml)
120
+
121
+ expect { t.bar }.to raise_error OM::XML::Terminology::BadPointerError
122
+ end
123
+
124
+ it "can get foo" do
125
+ subject.foo.should == ['fooval']
126
+ end
127
+
128
+ it "can get bar" do
129
+ subject.bar.should == ['barval']
130
+ end
131
+
132
+ end
133
+
134
+ end
@@ -0,0 +1,204 @@
1
+ require 'spec_helper'
2
+
3
+ describe "an example of xpath-y stuff, also using :proxy and :ref and namespaces" do
4
+
5
+ describe "a contrived example" do
6
+ before(:all) do
7
+ class XpathyStuffTerminology
8
+ include OM::XML::Document
9
+
10
+ set_terminology do |t|
11
+ t.root(:path=>"contentMetadata", :xmlns => '', :namespace_prefix => nil)
12
+
13
+ t.resource(:namespace_prefix => nil) {
14
+ t.file(:ref=>[:file], :namespace_prefix => nil)
15
+ }
16
+
17
+ t.file(:namespace_prefix => nil) {
18
+ t.location(:path=>"location", :namespace_prefix => nil)
19
+ t.filename(:path=>{:attribute=>"id"}, :namespace_prefix => nil)
20
+ t.format(:path=>{:attribute=>"format"}, :namespace_prefix => nil)
21
+ }
22
+ t.content(:ref=>:file, :path=>'resource/file[location="content"]', :namespace_prefix => nil)
23
+ t.html(:ref=>:file, :path=>'resource/file[location="html"]', :namespace_prefix => nil)
24
+
25
+ t.content_location(:proxy=>[:content, :location])
26
+ t.content_filename(:proxy=>[:content, :filename])
27
+ t.content_format(:proxy=>[:content, :format])
28
+
29
+ t.html_location(:proxy=>[:html, :location])
30
+ t.html_filename(:proxy=>[:html, :filename])
31
+ t.html_format(:proxy=>[:html, :format])
32
+
33
+ end
34
+ end
35
+ end
36
+
37
+ subject do
38
+ XpathyStuffTerminology.from_xml <<-EOF
39
+ <contentMetadata>
40
+ <resource type="file" id="BU3A5" objectId="val2">
41
+ <file id="BURCH1" format="BINARY">
42
+ <location>content</location>
43
+ </file>
44
+ <file id="BURCH1.html" format="HTML">
45
+ <location>html</location>
46
+ </file>
47
+ </resource>
48
+ </contentMetadata>
49
+
50
+ EOF
51
+ end
52
+
53
+ it "should have a content term" do
54
+ subject.content.first.should =~ /content/
55
+ end
56
+
57
+ it "should have an html term" do
58
+ subject.html.first.should =~ /html/
59
+ end
60
+
61
+
62
+ end
63
+
64
+ describe "an example from MODS" do
65
+ before(:all) do
66
+ class ModsXpathyStuffTerminology
67
+ include OM::XML::Document
68
+
69
+ set_terminology do |t|
70
+ t.root(:path=>"mods", :xmlns=>"http://www.loc.gov/mods/v3")
71
+ t.person(:path=>"name", :namespace_prefix => nil) {
72
+ t.given(:path=>"namePart", :attributes=>{:type=>"given"})
73
+ t.family(:path=>"namePart", :attributes=>{:type=>"family"})
74
+ t.role(:namespace_prefix => nil) {
75
+ t.text(:path=>"roleTerm", :attributes=>{:type=>"text"})
76
+ t.code(:path=>"roleTerm", :attributes=>{:type=>"code"})
77
+ }
78
+ }
79
+ t.author(:ref=>:person, :path=>'name[./role/roleTerm="aut"]')
80
+ t.advisor(:ref=>:person, :path=>'name[./role/roleTerm="ths"]')
81
+
82
+ t.author_given(:proxy=>[:author, :given])
83
+ t.author_family(:proxy=>[:author, :family])
84
+ t.advisor_given(:proxy=>[:advisor, :given])
85
+ t.advisor_family(:proxy=>[:advisor, :family])
86
+ end
87
+ end
88
+ end
89
+
90
+ subject do
91
+ ModsXpathyStuffTerminology.from_xml <<-EOF
92
+ <mods xmlns="http://www.loc.gov/mods/v3"
93
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3"
94
+ xsi:schemaLocation="http://www.loc.gov/mods/v3
95
+ http://www.loc.gov/standards/mods/v3/mods-3-3.xsd">
96
+ <name type="personal">
97
+ <namePart type="given">Mary</namePart>
98
+ <namePart type="family">Pickral</namePart>
99
+ <affiliation>University of Virginia</affiliation>
100
+ <namePart>mpc3c</namePart>
101
+ <affiliation>University of Virginia Library</affiliation>
102
+ <role>
103
+ <roleTerm authority="marcrelator" type="code">aut</roleTerm>
104
+ <roleTerm authority="marcrelator" type="text">author</roleTerm>
105
+ </role>
106
+ </name>
107
+ <name type="personal">
108
+ <namePart>der5y</namePart>
109
+ <namePart type="given">David</namePart>
110
+ <namePart type="family">Jones</namePart>
111
+ <affiliation>University of Virginia</affiliation>
112
+ <affiliation>Architectural History Dept.</affiliation>
113
+ <role>
114
+ <roleTerm authority="marcrelator" type="code">ths</roleTerm>
115
+ <roleTerm authority="marcrelator" type="text">advisor</roleTerm>
116
+ </role>
117
+ </name>
118
+ </mods>
119
+ EOF
120
+ end
121
+
122
+ it "should have the terms :author_given and :author_family to get the author name" do
123
+ pending "This doesn't seem to work?"
124
+ subject.author_given.should include("Mary")
125
+ subject.author_family.should include("Pickral")
126
+ end
127
+
128
+ it "should have the terms :advisor_given and :advisor_family to get the advisor name" do
129
+ pending "This doesn't seem to work?"
130
+ subject.advisor_given.should include("David")
131
+ subject.advisor_family.should include("Small")
132
+ end
133
+
134
+ end
135
+
136
+ describe "more MODS examples, with a given namespace prefix?" do
137
+
138
+ before(:all) do
139
+ class ModsXpathyStuffTerminology
140
+ include OM::XML::Document
141
+
142
+ set_terminology do |t|
143
+ t.root(:path=>"mods", :xmlns=>"http://www.loc.gov/mods/v3", :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-3.xsd", :namespace_prefix => "mods")
144
+
145
+ t.name_ {
146
+ t.name_part(:path=>"namePart")
147
+ t.family_name(:path=>"namePart", :attributes=>{:type=>"family"})
148
+ t.given_name(:path=>"namePart", :attributes=>{:type=>"given"}, :label=>"first name")
149
+ t.terms_of_address(:path=>"namePart", :attributes=>{:type=>"termsOfAddress"})
150
+ t.role(:ref=>[:role])
151
+ }
152
+ t.role {
153
+ t.role_term_text(:path=>"roleTerm", :attributes=>{:type=>"text"})
154
+ }
155
+
156
+ t.person_full(:ref=>:name, :attributes=>{:type=>"personal"})
157
+ t.person(:proxy=>[:person_full, :name_part])
158
+ t.creator(:ref=>:person, :path=>'name[mods:role/mods:roleTerm="creator"]', :xmlns=>"http://www.loc.gov/mods/v3", :namespace_prefix => "mods")
159
+
160
+ t.corporate_full(:ref=>:name, :attributes=>{:type=>"corporate"})
161
+ t.corporate(:proxy=>[:corporate_full, :name_part])
162
+ t.repository(:ref=>:corporate, :path=>'name[mods:role/mods:roleTerm="repository"]', :xmlns=>"http://www.loc.gov/mods/v3", :namespace_prefix => "mods")
163
+ end
164
+ end
165
+ end
166
+
167
+ subject do
168
+ ModsXpathyStuffTerminology.from_xml <<-EOF
169
+ <mods:mods xmlns:mods="http://www.loc.gov/mods/v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3" xsi:schemaLocation="http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-3.xsd">
170
+
171
+ <mods:name type="personal">
172
+ <mods:namePart>David Small</mods:namePart>
173
+ <mods:role>
174
+ <mods:roleTerm authority="marcrelator" type="text">creator</mods:roleTerm>
175
+ </mods:role>
176
+ </mods:name>
177
+ <mods:name type="corporate">
178
+ <mods:namePart>Graphic Novel Repository</mods:namePart>
179
+ <mods:role>
180
+ <mods:roleTerm authority="local" type="text">repository</mods:roleTerm>
181
+ </mods:role>
182
+ </mods:name>
183
+ </mods:mods>
184
+ EOF
185
+ end
186
+
187
+ it "should give a creator value" do
188
+ subject.creator.should include "David Small"
189
+ end
190
+
191
+ it "should give a repository value" do
192
+ subject.repository.should include "Graphic Novel Repository"
193
+ end
194
+
195
+ it "should have a person term 'for more generic xml'" do
196
+ subject.person.should include "David Small"
197
+ end
198
+
199
+ it "should have a corporate term 'for more generic xml'" do
200
+ subject.corporate.should include "Graphic Novel Repository"
201
+ end
202
+ end
203
+ end
204
+
@@ -1,3 +1,11 @@
1
+ if ENV['COVERAGE'] and RUBY_VERSION =~ /^1.9/
2
+ require 'simplecov'
3
+ require 'simplecov-rcov'
4
+
5
+ SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
6
+ SimpleCov.start
7
+ end
8
+
1
9
  require 'om'
2
10
  require 'rspec'
3
11
  require 'equivalent-xml/rspec_matchers'