om 1.6.0 → 1.6.1

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.
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'