hydra-pbcore 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,96 @@
1
+ module HydraPbcore::Methods
2
+
3
+ # Module for inserting different types of PBcore xml nodes into
4
+ # an existing PBcore document
5
+
6
+ module ClassMethods
7
+
8
+ def publisher_template(opts={})
9
+ builder = Nokogiri::XML::Builder.new do |xml|
10
+ xml.pbcorePublisher {
11
+ xml.publisher
12
+ xml.publisherRole(:source=>"PBCore publisherRole")
13
+ }
14
+ end
15
+ return builder.doc.root
16
+ end
17
+
18
+ def contributor_template(opts={})
19
+ builder = Nokogiri::XML::Builder.new do |xml|
20
+ xml.pbcoreContributor {
21
+ xml.contributor
22
+ xml.contributorRole(:source=>"MARC relator terms")
23
+ }
24
+ end
25
+ return builder.doc.root
26
+ end
27
+
28
+ def previous_template(opts={})
29
+ builder = Nokogiri::XML::Builder.new do |xml|
30
+ xml.instantiationRelation {
31
+ xml.instantiationRelationType(:annotation=>"One of a multi-part instantiation") {
32
+ xml.text "Follows in Sequence"
33
+ }
34
+ xml.instantiationRelationIdentifier(:source=>"Rock and Roll Hall of Fame and Museum")
35
+ }
36
+ end
37
+ return builder.doc.root
38
+ end
39
+
40
+ def next_template(opts={})
41
+ builder = Nokogiri::XML::Builder.new do |xml|
42
+ xml.instantiationRelation {
43
+ xml.instantiationRelationType(:annotation=>"One of a multi-part instantiation") {
44
+ xml.text "Precedes in Sequence"
45
+ }
46
+ xml.instantiationRelationIdentifier(:source=>"Rock and Roll Hall of Fame and Museum")
47
+ }
48
+ end
49
+ return builder.doc.root
50
+ end
51
+
52
+ end
53
+
54
+ def self.included(klass)
55
+ klass.extend(ClassMethods)
56
+ end
57
+
58
+ def insert_node(type, opts={})
59
+
60
+ unless self.class.respond_to?("#{type}_template".to_sym)
61
+ raise "No XML template is defined for a PBcore node of type #{type}."
62
+ end
63
+
64
+ node = self.class.send("#{type}_template".to_sym)
65
+ nodeset = self.find_by_terms(type.to_sym)
66
+
67
+ unless nodeset.nil?
68
+ if nodeset.empty?
69
+ if opts[:root]
70
+ self.find_by_terms(opts[:root].to_sym).first.add_child(node)
71
+ else
72
+ self.ng_xml.root.add_child(node)
73
+ end
74
+ index = 0
75
+ else
76
+ nodeset.after(node)
77
+ index = nodeset.length
78
+ end
79
+ self.dirty = true
80
+ end
81
+
82
+ return node, index
83
+
84
+ end
85
+
86
+ def remove_node(type, index)
87
+ if type == "education" or type == "television"
88
+ self.find_by_terms(type.to_sym).slice(index.to_i).parent.remove
89
+ else
90
+ self.find_by_terms(type.to_sym).slice(index.to_i).remove
91
+ end
92
+ self.dirty = true
93
+ end
94
+
95
+
96
+ end
@@ -0,0 +1,169 @@
1
+ require "spec_helper"
2
+
3
+ describe HydraPbcore::Datastream::DigitalDocument do
4
+
5
+ before(:each) do
6
+ @object_ds = HydraPbcore::Datastream::DigitalDocument.new(nil, nil)
7
+ end
8
+
9
+ describe ".update_indexed_attributes" do
10
+ it "should update all of the fields in #xml_template and fields not requiring additional inserted nodes" do
11
+ [
12
+ [:pbc_id],
13
+ [:main_title],
14
+ [:alternative_title],
15
+ [:chapter],
16
+ [:episode],
17
+ [:label],
18
+ [:segment],
19
+ [:subtitle],
20
+ [:track],
21
+ [:translation],
22
+ [:summary],
23
+ [:parts_list],
24
+ [:lc_subject],
25
+ [:lc_name],
26
+ [:rh_subject],
27
+ [:getty_genre],
28
+ [:lc_genre],
29
+ [:lc_subject_genre],
30
+ [:event_series],
31
+ [:event_place],
32
+ [:event_date],
33
+ [:contributor_name],
34
+ [:contributor_role],
35
+ [:publisher_name],
36
+ [:publisher_role],
37
+ [:note],
38
+ [:archival_collection],
39
+ [:archival_series],
40
+ [:collection_number],
41
+ [:accession_number],
42
+ [:usage],
43
+ ].each do |pointer|
44
+ test_val = "#{pointer.last.to_s} value"
45
+ @object_ds.update_values( {pointer=>{"0"=>test_val}} )
46
+ @object_ds.get_values(pointer).first.should == test_val
47
+ @object_ds.get_values(pointer).length.should == 1
48
+ end
49
+ end
50
+
51
+ it "should work for fields that require added xml nodes" do
52
+ @object_ds.insert_node("publisher")
53
+ @object_ds.insert_node("contributor")
54
+ [
55
+ [:publisher_name],
56
+ [:publisher_role],
57
+ [:contributor_name],
58
+ [:contributor_role]
59
+ ].each do |pointer|
60
+ test_val = "#{pointer.last.to_s} value"
61
+ @object_ds.update_indexed_attributes( {pointer=>{"0"=>test_val}} )
62
+ @object_ds.get_values(pointer).first.should == test_val
63
+ @object_ds.get_values(pointer).length.should == 1
64
+ end
65
+ end
66
+
67
+ it "should differentiate between multiple added nodes" do
68
+ @object_ds.insert_node(:contributor)
69
+ @object_ds.insert_node(:contributor)
70
+ @object_ds.update_indexed_attributes( {[:contributor_name] => { 0 => "first contributor" }} )
71
+ @object_ds.update_indexed_attributes( {[:contributor_name] => { 1 => "second contributor" }} )
72
+ @object_ds.update_indexed_attributes( {[:contributor_role] => { 0 => "first contributor role" }} )
73
+ @object_ds.update_indexed_attributes( {[:contributor_role] => { 1 => "second contributor role" }} )
74
+ @object_ds.get_values(:contributor).length.should == 2
75
+ @object_ds.get_values(:contributor_name)[0].should == "first contributor"
76
+ @object_ds.get_values(:contributor_name)[1].should == "second contributor"
77
+ @object_ds.get_values(:contributor_role)[0].should == "first contributor role"
78
+ @object_ds.get_values(:contributor_role)[1].should == "second contributor role"
79
+ end
80
+
81
+ end
82
+
83
+ describe "#xml_template" do
84
+ it "should return an empty xml document matching a valid exmplar" do
85
+ # insert additional nodes
86
+ @object_ds.insert_node("publisher")
87
+ @object_ds.insert_node("contributor")
88
+ @object_ds.insert_node("publisher")
89
+ @object_ds.insert_node("contributor")
90
+
91
+ # update additional nodes that OM will insert automatically
92
+ @object_ds.update_indexed_attributes({ [:alternative_title] => { 0 => "inserted" }} )
93
+ @object_ds.update_indexed_attributes({ [:chapter] => { 0 => "inserted" }} )
94
+ @object_ds.update_indexed_attributes({ [:episode] => { 0 => "inserted" }} )
95
+ @object_ds.update_indexed_attributes({ [:label] => { 0 => "inserted" }} )
96
+ @object_ds.update_indexed_attributes({ [:segment] => { 0 => "inserted" }} )
97
+ @object_ds.update_indexed_attributes({ [:subtitle] => { 0 => "inserted" }} )
98
+ @object_ds.update_indexed_attributes({ [:track] => { 0 => "inserted" }} )
99
+ @object_ds.update_indexed_attributes({ [:translation] => { 0 => "inserted" }} )
100
+ @object_ds.update_indexed_attributes({ [:lc_subject] => { 0 => "inserted" }} )
101
+ @object_ds.update_indexed_attributes({ [:lc_name] => { 0 => "inserted" }} )
102
+ @object_ds.update_indexed_attributes({ [:rh_subject] => { 0 => "inserted" }} )
103
+ @object_ds.update_indexed_attributes({ [:getty_genre] => { 0 => "inserted" }} )
104
+ @object_ds.update_indexed_attributes({ [:lc_genre] => { 0 => "inserted" }} )
105
+ @object_ds.update_indexed_attributes({ [:lc_subject_genre] => { 0 => "inserted" }} )
106
+ @object_ds.update_indexed_attributes({ [:subject] => { 0 => "inserted" }} )
107
+ @object_ds.update_indexed_attributes({ [:genre] => { 0 => "inserted" }} )
108
+
109
+ # Load example fixture
110
+ f = fixture "pbcore_digital_document_template.xml"
111
+ ref_node = Nokogiri::XML(f)
112
+ f.close
113
+
114
+ # Nokogiri-fy our sample document and reorder nodes
115
+ sample_node = Nokogiri::XML(@object_ds.to_xml)
116
+ reordered = HydraPbcore::Behaviors.reorder_document(sample_node)
117
+
118
+ # Save this for later...
119
+ out = File.new("tmp/pbcore_digital_document_sample.xml", "w")
120
+ out.write(reordered.to_s)
121
+ out.close
122
+
123
+ EquivalentXml.equivalent?(ref_node, reordered, opts = { :element_order => false, :normalize_whitespace => true }).should be_true
124
+ HydraPbcore::Behaviors.validate(reordered).should be_empty
125
+
126
+ end
127
+ end
128
+
129
+ describe ".insert_node" do
130
+ it "should return a node and index for a given template type" do
131
+ ["publisher", "contributor"].each do |type|
132
+ node, index = @object_ds.insert_node(type.to_s)
133
+ index.should == 0
134
+ @object_ds.dirty?.should be_true
135
+ node, index = @object_ds.insert_node(type.to_s)
136
+ index.should == 1
137
+ end
138
+ end
139
+
140
+ it "should raise an exception for non-exisitent templates" do
141
+ lambda { @object_ds.insert_node("blarg") }.should raise_error
142
+ end
143
+ end
144
+
145
+ describe ".remove_node" do
146
+ it "should remove a node a given type and index" do
147
+ ["publisher", "contributor"].each do |type|
148
+ @object_ds.insert_node(type.to_sym)
149
+ @object_ds.insert_node(type.to_sym)
150
+ @object_ds.find_by_terms(type.to_sym).count.should == 2
151
+ @object_ds.remove_node(type.to_sym, "1")
152
+ @object_ds.find_by_terms(type.to_sym).count.should == 1
153
+ @object_ds.remove_node(type.to_sym, "0")
154
+ @object_ds.find_by_terms(type.to_sym).count.should == 0
155
+ end
156
+ end
157
+
158
+ end
159
+
160
+ describe "default fields" do
161
+
162
+ it "such as media type should be 'Moving image'" do
163
+ pending "No default fields defined yet"
164
+ @object_ds.get_values([:media_type]).first.should == "Moving image"
165
+ end
166
+
167
+ end
168
+
169
+ end
@@ -0,0 +1,189 @@
1
+ require "spec_helper"
2
+
3
+ describe HydraPbcore::Datastream::Document do
4
+
5
+ before(:each) do
6
+ @object_ds = HydraPbcore::Datastream::Document.new(nil, nil)
7
+ end
8
+
9
+ describe ".update_indexed_attributes" do
10
+ it "should update all of the fields in #xml_template and fields not requiring additional inserted nodes" do
11
+ [
12
+ [:pbc_id],
13
+ [:main_title],
14
+ [:alternative_title],
15
+ [:chapter],
16
+ [:episode],
17
+ [:label],
18
+ [:segment],
19
+ [:subtitle],
20
+ [:track],
21
+ [:translation],
22
+ [:summary],
23
+ [:parts_list],
24
+ [:lc_subject],
25
+ [:lc_name],
26
+ [:rh_subject],
27
+ [:getty_genre],
28
+ [:lc_genre],
29
+ [:lc_subject_genre],
30
+ [:event_series],
31
+ [:event_place],
32
+ [:event_date],
33
+ [:contributor_name],
34
+ [:contributor_role],
35
+ [:publisher_name],
36
+ [:publisher_role],
37
+ [:note],
38
+ [:creation_date],
39
+ [:barcode],
40
+ [:repository],
41
+ [:format],
42
+ [:standard],
43
+ [:media_type],
44
+ [:generation],
45
+ [:language],
46
+ [:colors],
47
+ [:archival_collection],
48
+ [:archival_series],
49
+ [:collection_number],
50
+ [:accession_number],
51
+ [:usage],
52
+ [:condition_note],
53
+ [:cleaning_note]
54
+ ].each do |pointer|
55
+ test_val = "#{pointer.last.to_s} value"
56
+ @object_ds.update_values( {pointer=>{"0"=>test_val}} )
57
+ @object_ds.get_values(pointer).first.should == test_val
58
+ @object_ds.get_values(pointer).length.should == 1
59
+ end
60
+ end
61
+
62
+ it "should work for fields that require added xml nodes" do
63
+ @object_ds.insert_node("publisher")
64
+ @object_ds.insert_node("contributor")
65
+ [
66
+ [:publisher_name],
67
+ [:publisher_role],
68
+ [:contributor_name],
69
+ [:contributor_role]
70
+ ].each do |pointer|
71
+ test_val = "#{pointer.last.to_s} value"
72
+ @object_ds.update_indexed_attributes( {pointer=>{"0"=>test_val}} )
73
+ @object_ds.get_values(pointer).first.should == test_val
74
+ @object_ds.get_values(pointer).length.should == 1
75
+ end
76
+ end
77
+
78
+ it "should differentiate between multiple added nodes" do
79
+ @object_ds.insert_node(:contributor)
80
+ @object_ds.insert_node(:contributor)
81
+ @object_ds.update_indexed_attributes( {[:contributor_name] => { 0 => "first contributor" }} )
82
+ @object_ds.update_indexed_attributes( {[:contributor_name] => { 1 => "second contributor" }} )
83
+ @object_ds.update_indexed_attributes( {[:contributor_role] => { 0 => "first contributor role" }} )
84
+ @object_ds.update_indexed_attributes( {[:contributor_role] => { 1 => "second contributor role" }} )
85
+ @object_ds.get_values(:contributor).length.should == 2
86
+ @object_ds.get_values(:contributor_name)[0].should == "first contributor"
87
+ @object_ds.get_values(:contributor_name)[1].should == "second contributor"
88
+ @object_ds.get_values(:contributor_role)[0].should == "first contributor role"
89
+ @object_ds.get_values(:contributor_role)[1].should == "second contributor role"
90
+ end
91
+
92
+ end
93
+
94
+ describe "#xml_template" do
95
+ it "should return an empty xml document matching a valid exmplar" do
96
+ # insert additional nodes
97
+ @object_ds.insert_node("publisher")
98
+ @object_ds.insert_node("contributor")
99
+ @object_ds.insert_node("publisher")
100
+ @object_ds.insert_node("contributor")
101
+
102
+ # update additional nodes that OM will insert automatically
103
+ @object_ds.update_indexed_attributes({ [:alternative_title] => { 0 => "inserted" }} )
104
+ @object_ds.update_indexed_attributes({ [:chapter] => { 0 => "inserted" }} )
105
+ @object_ds.update_indexed_attributes({ [:episode] => { 0 => "inserted" }} )
106
+ @object_ds.update_indexed_attributes({ [:label] => { 0 => "inserted" }} )
107
+ @object_ds.update_indexed_attributes({ [:segment] => { 0 => "inserted" }} )
108
+ @object_ds.update_indexed_attributes({ [:subtitle] => { 0 => "inserted" }} )
109
+ @object_ds.update_indexed_attributes({ [:track] => { 0 => "inserted" }} )
110
+ @object_ds.update_indexed_attributes({ [:translation] => { 0 => "inserted" }} )
111
+ @object_ds.update_indexed_attributes({ [:lc_subject] => { 0 => "inserted" }} )
112
+ @object_ds.update_indexed_attributes({ [:lc_name] => { 0 => "inserted" }} )
113
+ @object_ds.update_indexed_attributes({ [:rh_subject] => { 0 => "inserted" }} )
114
+ @object_ds.update_indexed_attributes({ [:getty_genre] => { 0 => "inserted" }} )
115
+ @object_ds.update_indexed_attributes({ [:lc_genre] => { 0 => "inserted" }} )
116
+ @object_ds.update_indexed_attributes({ [:lc_subject_genre] => { 0 => "inserted" }} )
117
+ @object_ds.update_indexed_attributes({ [:subject] => { 0 => "inserted" }} )
118
+ @object_ds.update_indexed_attributes({ [:genre] => { 0 => "inserted" }} )
119
+ @object_ds.update_indexed_attributes({ [:condition_note] => { 0 => "inserted" }} )
120
+ @object_ds.update_indexed_attributes({ [:cleaning_note] => { 0 => "inserted" }} )
121
+
122
+ # Load example fixture
123
+ f = fixture "pbcore_document_template.xml"
124
+ ref_node = Nokogiri::XML(f)
125
+ f.close
126
+
127
+ # Nokogiri-fy our sample document and reorder nodes
128
+ sample_node = Nokogiri::XML(@object_ds.to_xml)
129
+ reordered = HydraPbcore::Behaviors.reorder_document(sample_node)
130
+
131
+ # Save this for later...
132
+ out = File.new("tmp/pbcore_document_sample.xml", "w")
133
+ out.write(reordered.to_s)
134
+ out.close
135
+
136
+ EquivalentXml.equivalent?(ref_node, reordered, opts = { :element_order => false, :normalize_whitespace => true }).should be_true
137
+ HydraPbcore::Behaviors.validate(reordered).should be_empty
138
+
139
+ end
140
+ end
141
+
142
+ describe ".insert_node" do
143
+ it "should return a node and index for a given template type" do
144
+ ["publisher", "contributor"].each do |type|
145
+ node, index = @object_ds.insert_node(type.to_s)
146
+ index.should == 0
147
+ @object_ds.dirty?.should be_true
148
+ node, index = @object_ds.insert_node(type.to_s)
149
+ index.should == 1
150
+ end
151
+ end
152
+
153
+ it "should raise an exception for non-exisitent templates" do
154
+ lambda { @object_ds.insert_node("blarg") }.should raise_error
155
+ end
156
+ end
157
+
158
+ describe ".remove_node" do
159
+ it "should remove a node a given type and index" do
160
+ ["publisher", "contributor"].each do |type|
161
+ @object_ds.insert_node(type.to_sym)
162
+ @object_ds.insert_node(type.to_sym)
163
+ @object_ds.find_by_terms(type.to_sym).count.should == 2
164
+ @object_ds.remove_node(type.to_sym, "1")
165
+ @object_ds.find_by_terms(type.to_sym).count.should == 1
166
+ @object_ds.remove_node(type.to_sym, "0")
167
+ @object_ds.find_by_terms(type.to_sym).count.should == 0
168
+ end
169
+ end
170
+
171
+ end
172
+
173
+ describe "default fields" do
174
+
175
+ it "such as media type should be 'Moving image'" do
176
+ @object_ds.get_values([:media_type]).first.should == "Moving image"
177
+ end
178
+
179
+ it "such as colors should be 'Color'" do
180
+ @object_ds.get_values([:colors]).first.should == "Color"
181
+ end
182
+
183
+ it "such as generation should be 'Original'" do
184
+ @object_ds.get_values([:generation]).first.should == "Original"
185
+ end
186
+
187
+ end
188
+
189
+ end