uwdc 0.0.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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MzZmZTU4NjE2MmIyNDdlYTdiYzI4NjlhNTc0NDNiYTAxYzYyZWZjMw==
5
+ data.tar.gz: !binary |-
6
+ ZGQyOTczOTcxZjlmZTIwNjhkZWFmMDc3YzEzMjE1MjExMmI5ZWI0OA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ ODFkNzNlNjVmNThiMDNkNGM1OGMyZGEwMGY1YzM1NWY0NDg2ZDcyODRmNzBj
10
+ NDg4N2I1Zjg5MjA1NjU3OTc4ZWY1MjZkZDc2MjIzYjcyYmQ0ZjgxN2RjMWFl
11
+ NzAyNzFkYWVhNjFkOWZjMmRmZWUyNjUwNGE5YjNkNTA2YTRkMTM=
12
+ data.tar.gz: !binary |-
13
+ ODc5NTM2YzE1OTRmODgzYjJjOTU5MzQ1YmZiOWE5ZDk1Y2Y2YWE4M2UxNGVh
14
+ NWY3MzllYzA3N2QzNzVhZTExOGJiNzRhMWEzMzM4MjgwYzBkMTliZjhhNTVl
15
+ ZDMxNmRlYjM2YTcwNWJjNGExNWQ2ZDg5ZDEzNzUzYTcyZTYwMTM=
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --format documentation --color
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-1.9.3-p392
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in uwdc.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,13 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec' do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/uwdc/(.+)\.rb$}) { |m| "spec/models/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Turnip features and steps
10
+ watch(%r{^spec/acceptance/(.+)\.feature$})
11
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
12
+ end
13
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Board of Regents - University of Wisconsin System
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,111 @@
1
+ UWDC
2
+ ====
3
+
4
+ [![Build Status](https://travis-ci.org/ewlarson/uwdc.png)](https://travis-ci.org/ewlarson/uwdc)
5
+ [![Dependency Status](https://gemnasium.com/ewlarson/uwdc.png)](https://gemnasium.com/ewlarson/uwdc)
6
+ [![Code Climate](https://codeclimate.com/github/ewlarson/uwdc.png)](https://codeclimate.com/github/ewlarson/uwdc)
7
+
8
+ ## Synopsis
9
+
10
+ Gem for accessing University of Wisconsin Digital Collection items from our Fedora Commons repository.
11
+
12
+ ## Usage
13
+
14
+ ### METS
15
+ Obtain the METS metadata for a UWDC object.
16
+
17
+ ```ruby
18
+ require 'uwdc'
19
+ mets = UWDC::Mets.new('33QOBSVPJLWEM8S') # Ignoring
20
+ mets.mods
21
+ mets.mods.titles
22
+ ```
23
+
24
+ UWDC METS will contain:
25
+
26
+ * MODS
27
+ * Origin (PREMIS)
28
+ * RELS-EXT
29
+ * FileSec
30
+ * StructMap
31
+
32
+ ### MODS
33
+ Obtain the MODS metadata for a UWDC object.
34
+
35
+ ```ruby
36
+ mods = UWDC::Mods.new('33QOBSVPJLWEM8S')
37
+ mods.titles
38
+ ```
39
+ MODS top-level elements are boiled in Ruby to something more dot-syntax friendly.
40
+
41
+ <table>
42
+ <thead>
43
+ <tr>
44
+ <th>UWDC::Mods method</th>
45
+ <th>MODS Element</th>
46
+ <th>Example output</th>
47
+ </tr>
48
+ </thead>
49
+ <tbody>
50
+ <tr>
51
+ <td>mods.titles</td>
52
+ <td>titleInfo</td>
53
+ <td>["A life idyl", ...]</td>
54
+ </tr>
55
+ <tr>
56
+ <td>mods.names</td>
57
+ <td>name</td>
58
+ <td>[OpenStruct.new(:name, :role), ...]</td>
59
+ </tr>
60
+ <tr>
61
+ <td>mods.dates</td>
62
+ <td>originInfo</td>
63
+ <td>["1869"]</td>
64
+ </tr>
65
+ <tr>
66
+ <td>mods.forms</td>
67
+ <td>physicalDescription</td>
68
+ <td>["text"]</td>
69
+ </tr>
70
+ <tr>
71
+ <td>mods.abstracts</td>
72
+ <td>abstract</td>
73
+ <td>["Green leather with gold stamping...", ...]</td>
74
+ </tr>
75
+ <tr>
76
+ <td>mods.subjects</td>
77
+ <td>subject</td>
78
+ <td>["Bookbinding--Techniques--Gold stamping", ...]</td>
79
+ </tr>
80
+ <tr>
81
+ <td>mods.access_conditions</td>
82
+ <td>accessCondition</td>
83
+ <td>[OpenStruct.new(:rights, :reuse), ...]</td>
84
+ </tr>
85
+ <tr>
86
+ <td>mods.related_items</td>
87
+ <td>relatedItem</td>
88
+ <td>[OpenStruct.new(:label, :name), ...]</td>
89
+ </tr>
90
+ </tbody>
91
+ </table>
92
+
93
+ ```ruby
94
+ # Transform via to_* calls
95
+ # - supports JSON, Ruby and XML
96
+ mods.to_json
97
+ mods.to_ruby
98
+ mods.to_xml
99
+ ```
100
+
101
+ ## Changelog
102
+
103
+ Nothing to mention yet.
104
+
105
+ ## Contributors
106
+
107
+ Eric Larson
108
+
109
+ ## Copyright
110
+
111
+ UWDC © 2013 Board of Regents - University of Wisconsin System. UWDC is licensed under the MIT license. Please see the LICENSE for more information.
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task :default => :spec
7
+ task :test => :spec
data/lib/uwdc.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'uwdc/version'
2
+ require 'httpclient/include_client'
3
+ require 'httpclient'
4
+ require 'nokogiri'
5
+ require 'json'
6
+ require 'active_support/core_ext/hash'
7
+
8
+ # UWDC
9
+ module UWDC
10
+ XmlNotFound = Class.new(StandardError)
11
+ end
12
+
13
+ require 'uwdc/mets'
14
+ require 'uwdc/mods'
15
+ require 'uwdc/origin'
16
+ require 'uwdc/rels_ext'
17
+ require 'uwdc/file_sec'
18
+ require 'uwdc/struct_map'
19
+ require 'uwdc/display'
20
+ require 'uwdc/dublin_core'
21
+ require 'uwdc/xml'
@@ -0,0 +1,91 @@
1
+ module UWDC
2
+ # Return an object to drive the display of UWDC items
3
+ class Display
4
+
5
+ attr_accessor :mets, :title, :visual_representation
6
+
7
+ def initialize(id, xml=nil)
8
+ @mets = UWDC::Mets.new(id,xml)
9
+ end
10
+
11
+ def use
12
+ {
13
+ "title" => { :view => false, :partial => "text" },
14
+ "visualrepresentation" => { :view => false, :partial => "text" },
15
+ "icon" => { :view => true, :partial => "image" },
16
+ "thumb" => { :view => true, :partial => "image" },
17
+ "reference" => { :view => true, :partial => "image" },
18
+ "large" => { :view => true, :partial => "image" },
19
+ "audiostream" => { :view => true, :partial => "audio" }
20
+ }
21
+ end
22
+
23
+ def cmodels
24
+ {
25
+ "info:fedora/1711.dl:CModelAudio" => { :view => true, :partial => "audio" },
26
+ "info:fedora/1711.dl:CModelAudioStream" => { :view => true, :partial => "audio" },
27
+ "info:fedora/1711.dl:CModelCompositeObject" => { :view => true, :partial => "set" },
28
+ "info:fedora/1711.dl:CModelCollection" => { :view => true, :partial => "collection" },
29
+ "info:fedora/1711.dl:CModelCompositeObject" => { :view => false, :partial => nil },
30
+ "info:fedora/1711.dl:CModelCompositeSequenceObject" => { :view => true, :partial => "image-with-sequence" },
31
+ "info:fedora/1711.dl:CModelFirstClassObject" => { :view => false, :partial => nil },
32
+ "info:fedora/1711.dl:CModelImageWithDefaultRes" => { :view => true, :partial => "image" },
33
+ "info:fedora/1711.dl:CModelImageWithDetail" => { :view => true, :partial => "image-with-detail" },
34
+ "info:fedora/1711.dl:CModelImageWithSequence" => { :view => true, :partial => "image-with-sequence" },
35
+ "info:fedora/1711.dl:CModelImageWithXLarge" => { :view => true, :partial => "image-with-xlarge" },
36
+ "info:fedora/1711.dl:CModelImageWithZoom" => { :view => true, :partial => "image-with-zoom" },
37
+ "info:fedora/1711.dl:CModelSimpleDocument" => { :view => true, :partial => "download" },
38
+ "info:fedora/1711.dl:CModelUWDCObject" => { :view => false, :partial => nil }
39
+ }
40
+ end
41
+
42
+ def files
43
+ @mets.file_sec.files
44
+ end
45
+
46
+ def image_files(model)
47
+ files.select{|file| file.id.include?(model) && use[file.use][:partial] == "image"}
48
+ end
49
+
50
+ def images
51
+ viewable_models.inject({}) do |result, model|
52
+ result[model] = image_files(model)
53
+ result
54
+ end
55
+ end
56
+
57
+ def video
58
+ end
59
+
60
+ def audio
61
+ end
62
+
63
+ def mods
64
+ @mets.mods
65
+ end
66
+
67
+ alias :metadata :mods
68
+
69
+ private
70
+
71
+ def content_models
72
+ @mets.rels_ext.models
73
+ end
74
+
75
+ def viewable_model?(model)
76
+ model.last.detect{|name| cmodels[name][:view] == true}
77
+ end
78
+
79
+ def viewable_models
80
+ content_models.inject([]) do |result, model|
81
+ result << clean_id(model.first) if viewable_model?(model)
82
+ result
83
+ end
84
+ end
85
+
86
+ def clean_id(id)
87
+ clean = id.split("-")
88
+ "#{clean[0]}-#{clean[1]}"
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,34 @@
1
+ module UWDC
2
+ # Return dublin core based metadata associated with METS files
3
+ class DublinCore < Mets
4
+ def nodes
5
+ @xml.nodes.xpath("//dmdSec//dc")
6
+ end
7
+
8
+ def titles
9
+ nodes.inject({}) do |result, children|
10
+ result[capture_id(children)] = capture_title(children)
11
+ result
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def capture_id(children)
18
+ fix_id(clean_nodes(children.xpath(".//identifier[1]"))[0])
19
+ end
20
+
21
+ def capture_title(children)
22
+ clean_nodes(children.xpath(".//title[1]"))[0]
23
+ end
24
+
25
+ # @FIXME: UWDC identifiers are all jacked up
26
+ # - mets[@OBJID] => 1711.dl:FJIOAPU6Z7UKR8E
27
+ # - dmdSec[@ID] => x1711-dl_FJIOAPU6Z7UKR8E
28
+ # - mods/identifier[@type='handle'] => 1711.dl/FJIOAPU6Z7UKR8E
29
+ # - mods/recordInfo/recordIdentifier => 1711.dl:FJIOAPU6Z7UKR8E.BIB0ˇ
30
+ def fix_id(id)
31
+ "x#{id.gsub('.','-').gsub(':','_')}"
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,12 @@
1
+ module UWDC
2
+ # Return the METS files
3
+ class FileSec < Mets
4
+ def nodes
5
+ @xml.nodes.xpath("//fileSec")
6
+ end
7
+
8
+ def files
9
+ nodes.xpath("//fileGrp/file").inject([]){|result, file| result << FileAsset.new(file)}
10
+ end
11
+ end
12
+ end
data/lib/uwdc/mets.rb ADDED
@@ -0,0 +1,195 @@
1
+ module UWDC
2
+ # Public: Methods to obtain UWDC METS metadata via an object identifier.
3
+ #
4
+ # Examples
5
+ #
6
+ # UWDC::Mets.new('ECJ6ZXEYWUE7B8W')
7
+ # # => object fetched from Fedora
8
+ #
9
+ # UWDC::Mets.new('ECJ6ZXEYWUE7B8W', File.read('../file.xml'))
10
+ # # => object constructed from XML file
11
+ class Mets
12
+ attr_accessor :id, :xml
13
+
14
+ # Public: Intialize a UWDC Mets object
15
+ #
16
+ # id - A UWDC identifier.
17
+ # xml - An optional XML file.
18
+ #
19
+ # Raises XmlNotFound if the xml file cannot be found or fetched.
20
+ def initialize(id, xml=nil)
21
+ @id = id
22
+ @xml ||= UWDC::XML.new(@id,xml)
23
+ raise(XmlNotFound) unless [nil,200].include?(@xml.status)
24
+ end
25
+
26
+ # Public: Access the XML nodes of the METS file
27
+ #
28
+ # Example
29
+ #
30
+ # @mets.nodes
31
+ # # => Nokogiri::XML::NodeSet
32
+ #
33
+ # Returns the Nokogiri::XML::NodeSet for the parsed METS file
34
+ def nodes
35
+ @xml.nodes
36
+ end
37
+
38
+ # Public: Convert the XML nodes to JSON
39
+ #
40
+ # Example
41
+ #
42
+ # @mets.to_json
43
+ # # => {'mets': ...}
44
+ #
45
+ # Returns the Nokogiri::XML::NodeSet as JSON
46
+ def to_json
47
+ Hash.from_xml(nodes.to_xml).to_json
48
+ end
49
+
50
+ # Public: Convert the XML nodes to Ruby
51
+ #
52
+ # Example
53
+ #
54
+ # @mets.to_ruby
55
+ # # => {'mets': ...}
56
+ #
57
+ # Returns the Nokogiri::XML::NodeSet as a Ruby Hash
58
+ def to_ruby
59
+ Hash.from_xml(nodes.to_xml)
60
+ end
61
+
62
+ # Public: Convert the XML nodes to XML
63
+ #
64
+ # Example
65
+ #
66
+ # @mets.to_xml
67
+ # # => "<mets>..."
68
+ #
69
+ # Returns the Nokogiri::XML::NodeSet as XML
70
+ def to_xml
71
+ nodes.to_xml
72
+ end
73
+
74
+ # Public: Access the MODS descriptive metadata XML nodes
75
+ #
76
+ # Example
77
+ #
78
+ # @mets.mods
79
+ # # => UWDC::Mods
80
+ #
81
+ # Returns a UWDC::Mods object
82
+ def mods
83
+ @mods = Mods.new(@id)
84
+ end
85
+
86
+ # Public: Access the StructMap structural map section XML nodes
87
+ #
88
+ # Example
89
+ #
90
+ # @mets.struct_map
91
+ # # => UWDC::StructMap
92
+ #
93
+ # Returns a UWDC::StructMap object
94
+ def struct_map(id=@id)
95
+ @struct_map = StructMap.new(id)
96
+ end
97
+
98
+ # Public: Access the RelsExt RDF relation XML nodes
99
+ #
100
+ # Example
101
+ #
102
+ # @mets.rels_ext
103
+ # # => UWDC::RelsExt
104
+ #
105
+ # Returns a UWDC::RelsExt object
106
+ def rels_ext(id=@id)
107
+ @rels_ext = RelsExt.new(id)
108
+ end
109
+
110
+ # Public: Access the FileSec file section XML nodes
111
+ #
112
+ # Example
113
+ #
114
+ # @mets.file_sec
115
+ # # => UWDC::FileSec
116
+ #
117
+ # Returns a UWDC::FileSec object
118
+ def file_sec(id=@id)
119
+ @file_sec = FileSec.new(id)
120
+ end
121
+
122
+ # Public: Access the DublinCore descriptive metadata XML nodes
123
+ #
124
+ # Example
125
+ #
126
+ # @mets.dublin_core
127
+ # # => UWDC::DublinCore
128
+ #
129
+ # Returns a UWDC::DublinCore object
130
+ def dublin_core(id=@id)
131
+ @dublin_core = DublinCore.new(id)
132
+ end
133
+
134
+ # Public: Access the Display class/methods for the METS file
135
+ #
136
+ # Example
137
+ #
138
+ # @mets.display
139
+ # # => UWDC::Display
140
+ #
141
+ # Returns a UWDC::Display object
142
+ def display(id=@id)
143
+ @display = Display.new(id)
144
+ end
145
+
146
+ private
147
+
148
+ # Internal: Strip the id of it's ClassName
149
+ def identifier(id)
150
+ id[0,id.rindex(/[\.-]/)]
151
+ end
152
+
153
+ # Internal: Remove empty node entries
154
+ def clean_nodes(node_array)
155
+ node_array.map{|node| node.text}.reject(&:empty?)
156
+ end
157
+
158
+ # Internal: Select the attribute in a node array
159
+ def pick_attribute(node_array, attribute)
160
+ node_array.map{|node| node.attribute(attribute).value}.reject(&:empty?)
161
+ end
162
+ end
163
+
164
+ # Public: One division from the StructMap
165
+ class Div
166
+ attr_accessor :id, :admid, :order
167
+
168
+ def initialize(node)
169
+ @node = node
170
+ @id = node["ID"]
171
+ @admid = node["ADMID"]
172
+ @order = node["ORDER"] ? node["ORDER"] : ""
173
+ end
174
+
175
+ def file_pointers
176
+ @node.children.map{|node| node["FILEID"] if node.name == "fptr"}.compact
177
+ end
178
+
179
+ def kids
180
+ @node.children.map{|div| Div.new(div) if div.name == "div"}.compact
181
+ end
182
+ end
183
+
184
+ # Public: One file asset from the FileSec
185
+ class FileAsset
186
+ attr_accessor :id, :mimetype, :use, :href, :title
187
+
188
+ def initialize(node)
189
+ @id = node["ID"]
190
+ @mimetype = node["MIMETYPE"]
191
+ @use = node["USE"]
192
+ @href = node.children.detect{|child| child.name == "FLocat"}.attr('href')
193
+ end
194
+ end
195
+ end