mead 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +27 -0
- data/Gemfile.lock +56 -0
- data/LICENSE +20 -0
- data/README.rdoc +86 -0
- data/Rakefile +67 -0
- data/VERSION +1 -0
- data/bin/automead +53 -0
- data/bin/ead2meads +90 -0
- data/bin/emv +77 -0
- data/bin/mead2barcode +64 -0
- data/bin/meadbfv +27 -0
- data/lib/mead/barcode.rb +49 -0
- data/lib/mead/container.rb +21 -0
- data/lib/mead/ead.rb +215 -0
- data/lib/mead/ead_validator.rb +46 -0
- data/lib/mead/extractor.rb +198 -0
- data/lib/mead/identifier.rb +112 -0
- data/lib/mead/trollop.rb +38 -0
- data/lib/mead/validations.rb +130 -0
- data/lib/mead.rb +71 -0
- data/mead.gemspec +142 -0
- data/test/ead/mc00145.xml +157 -0
- data/test/ead/mc00240.xml +12523 -0
- data/test/ead/ua015_010.xml +31103 -0
- data/test/ead/ua021_428.xml +146 -0
- data/test/ead/ua023_006.xml +469 -0
- data/test/ead/ua023_031.xml +5202 -0
- data/test/ead/ua110_041.xml +4101 -0
- data/test/fixtures/mc00310.xml +186 -0
- data/test/fixtures/ua023_031.xml +5228 -0
- data/test/helper.rb +38 -0
- data/test/test_barcode.rb +25 -0
- data/test/test_ead.rb +193 -0
- data/test/test_ead_validator.rb +18 -0
- data/test/test_extractor.rb +83 -0
- data/test/test_mc00145.rb +19 -0
- data/test/test_mc00240.rb +140 -0
- data/test/test_mead.rb +5 -0
- data/test/test_ua015_010.rb +111 -0
- data/test/test_ua021_428.rb +26 -0
- data/test/test_ua023_006_buildings.rb +111 -0
- data/test/test_ua023_006_faculty.rb +112 -0
- data/test/test_ua110_041.rb +112 -0
- data/test/test_validations.rb +81 -0
- data/watchr.rb +71 -0
- metadata +338 -0
data/.document
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
gem "rmagick", ">= 0"
|
7
|
+
gem "nokogiri", "= 1.4.3.1"
|
8
|
+
gem "json", ">= 0"
|
9
|
+
gem "trollop", ">= 0"
|
10
|
+
|
11
|
+
gem "fastercsv", ">= 0", :platforms => :ruby_18
|
12
|
+
|
13
|
+
gem "gbarcode", ">= 0.98.20", :platforms => :ruby_18
|
14
|
+
|
15
|
+
|
16
|
+
# Add dependencies to develop your gem here.
|
17
|
+
# Include everything needed to run rake, tests, features, etc.
|
18
|
+
group :development do
|
19
|
+
gem "shoulda", ">= 0"
|
20
|
+
gem "bundler", "~> 1.0.0"
|
21
|
+
gem "jeweler", "~> 1.5.1"
|
22
|
+
gem "rcov", ">= 0"
|
23
|
+
gem "reek", "~> 1.2.8"
|
24
|
+
gem "roodi", "~> 2.1.0"
|
25
|
+
gem "fakeweb", ">= 0"
|
26
|
+
gem "ruby-debug"
|
27
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
columnize (0.3.2)
|
5
|
+
fakeweb (1.3.0)
|
6
|
+
fastercsv (1.5.4)
|
7
|
+
gbarcode (0.98.20)
|
8
|
+
git (1.2.5)
|
9
|
+
jeweler (1.5.2)
|
10
|
+
bundler (~> 1.0.0)
|
11
|
+
git (>= 1.2.5)
|
12
|
+
rake
|
13
|
+
json (1.5.0)
|
14
|
+
linecache (0.43)
|
15
|
+
nokogiri (1.4.3.1)
|
16
|
+
rake (0.8.7)
|
17
|
+
rcov (0.9.9)
|
18
|
+
reek (1.2.8)
|
19
|
+
ruby2ruby (~> 1.2)
|
20
|
+
ruby_parser (~> 2.0)
|
21
|
+
sexp_processor (~> 3.0)
|
22
|
+
rmagick (2.13.1)
|
23
|
+
roodi (2.1.0)
|
24
|
+
ruby_parser
|
25
|
+
ruby-debug (0.10.4)
|
26
|
+
columnize (>= 0.1)
|
27
|
+
ruby-debug-base (~> 0.10.4.0)
|
28
|
+
ruby-debug-base (0.10.4)
|
29
|
+
linecache (>= 0.3)
|
30
|
+
ruby2ruby (1.2.5)
|
31
|
+
ruby_parser (~> 2.0)
|
32
|
+
sexp_processor (~> 3.0)
|
33
|
+
ruby_parser (2.0.5)
|
34
|
+
sexp_processor (~> 3.0)
|
35
|
+
sexp_processor (3.0.5)
|
36
|
+
shoulda (2.11.3)
|
37
|
+
trollop (1.16.2)
|
38
|
+
|
39
|
+
PLATFORMS
|
40
|
+
ruby
|
41
|
+
|
42
|
+
DEPENDENCIES
|
43
|
+
bundler (~> 1.0.0)
|
44
|
+
fakeweb
|
45
|
+
fastercsv
|
46
|
+
gbarcode (>= 0.98.20)
|
47
|
+
jeweler (~> 1.5.1)
|
48
|
+
json
|
49
|
+
nokogiri (= 1.4.3.1)
|
50
|
+
rcov
|
51
|
+
reek (~> 1.2.8)
|
52
|
+
rmagick
|
53
|
+
roodi (~> 2.1.0)
|
54
|
+
ruby-debug
|
55
|
+
shoulda
|
56
|
+
trollop
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 North Carolina State University
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
= mead
|
2
|
+
|
3
|
+
Metadata from Encoded Archival Description.
|
4
|
+
|
5
|
+
The core of this code is an identifier which expresses the location of an object
|
6
|
+
in a physical collection. This identifier can be used as a filename for
|
7
|
+
digitized objects during scanning. Later descriptive metadata from EAD XML can
|
8
|
+
be extracted. This descriptive metadata can then be applied to stub records for
|
9
|
+
each digital object, which can quickly make digitized objects as discoverable as
|
10
|
+
the archival description makes the physical collections.
|
11
|
+
|
12
|
+
== Functionality
|
13
|
+
|
14
|
+
- Parse EAD XML and output all identifiers (with other metadata) for all the
|
15
|
+
component parts. This export can be CSV or JSON.
|
16
|
+
- Resolve a filename-identifier to a location in the physical collection and
|
17
|
+
extract related metadata up through the hierarchy
|
18
|
+
- Create barcodes based on an identifiers.
|
19
|
+
- Validate whether an identifier is well-formed and valid by resolving to a
|
20
|
+
component part in the EAD XML.
|
21
|
+
- Commandline tools for each of these functions.
|
22
|
+
|
23
|
+
== Installation
|
24
|
+
|
25
|
+
- clone from github and build the gem from source at this time
|
26
|
+
|
27
|
+
== Identifier specification in brief
|
28
|
+
|
29
|
+
These identifiers encode information about where original objects in the physical
|
30
|
+
collection are located. To make this work for as wide a range of encoded EAD XML
|
31
|
+
and archival arrangement and processing practice as we could, it includes many
|
32
|
+
pieces of information to help insure uniqueness within a collection.
|
33
|
+
|
34
|
+
Indentifiers are made up of 6 possible segments. Segments are separated by a
|
35
|
+
single dash - to aid in readability. Take the sample identifier
|
36
|
+
mc00240-001-ff0001-000-001_0001
|
37
|
+
|
38
|
+
1. mc00240: Collection number.
|
39
|
+
The first section identifies the collection and
|
40
|
+
is usually the eadid of the collection. mc00240 refers to
|
41
|
+
http://www.lib.ncsu.edu/findingaids/mc00240
|
42
|
+
|
43
|
+
2. 001: Series number.
|
44
|
+
This is the number of the series of which the physical
|
45
|
+
item is a part. It is a three digit, left zero padded number.
|
46
|
+
|
47
|
+
3. ff0001: Container code & number.
|
48
|
+
The third segment is made up of a two letter
|
49
|
+
code for different container types. The list of current codes can be seen in
|
50
|
+
lib/mead.rb as Mead::CONTAINER_MAPPING. (These are the codes NCSU uses for
|
51
|
+
encoding containers in EAD XML.) The second part is a three digit, left zero
|
52
|
+
padded number. This example would be flatfolder 1.
|
53
|
+
|
54
|
+
4. 000: Folder number.
|
55
|
+
In this case there is no second container, so the folder
|
56
|
+
number is 000. If there was a container with the "folder" value for the type
|
57
|
+
attribute and text content of "3", then this segment would be 003. In the case
|
58
|
+
where the value is other than "folder" the container code is used in front. So
|
59
|
+
a "mapcase" container could be "mc003" when the map case is the third map case
|
60
|
+
in the parent container.
|
61
|
+
|
62
|
+
5. 001: Item number.
|
63
|
+
This is the number of the item in the container. It is an
|
64
|
+
arbitrary incremented number. Multiple pages of multipage document would
|
65
|
+
be considered as one item and so would get the same item number.
|
66
|
+
|
67
|
+
6. _0001: Sequence number (optional).
|
68
|
+
If there is a multipage document then this
|
69
|
+
section can be used. This is the sequence or page number. It is preceded with
|
70
|
+
an underscore.
|
71
|
+
|
72
|
+
|
73
|
+
== TODO
|
74
|
+
|
75
|
+
- Test for use by other institutions. I'm happy to help make this code work for
|
76
|
+
the needs of other institutions.
|
77
|
+
- Get more examples for more tests.
|
78
|
+
- Better exceptions.
|
79
|
+
|
80
|
+
== Author
|
81
|
+
|
82
|
+
Jason Ronallo
|
83
|
+
|
84
|
+
== Copyright
|
85
|
+
|
86
|
+
Copyright (c) 2010 North Carolina State University. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'rake'
|
11
|
+
|
12
|
+
require 'jeweler'
|
13
|
+
Jeweler::Tasks.new do |gem|
|
14
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
+
gem.name = "mead"
|
16
|
+
gem.homepage = "http://github.com/jronallo/mead"
|
17
|
+
gem.license = "MIT"
|
18
|
+
gem.summary = %Q{Extract identifiers and metadata from EAD XML.}
|
19
|
+
gem.description = %Q{Extract identifiers and metadata from EAD XML.}
|
20
|
+
gem.email = "jronallo@gmail.com"
|
21
|
+
gem.authors = ["Jason Ronallo"]
|
22
|
+
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
23
|
+
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
24
|
+
# gem.add_runtime_dependency 'jabber4r', '> 0.1'
|
25
|
+
# gem.add_development_dependency 'rspec', '> 1.2.3'
|
26
|
+
end
|
27
|
+
Jeweler::RubygemsDotOrgTasks.new
|
28
|
+
|
29
|
+
require 'rake/testtask'
|
30
|
+
Rake::TestTask.new(:test) do |test|
|
31
|
+
test.libs << 'lib' << 'test'
|
32
|
+
test.pattern = 'test/**/test_*.rb'
|
33
|
+
test.verbose = true
|
34
|
+
end
|
35
|
+
|
36
|
+
require 'rcov/rcovtask'
|
37
|
+
Rcov::RcovTask.new do |test|
|
38
|
+
test.libs << 'test'
|
39
|
+
test.pattern = 'test/**/test_*.rb'
|
40
|
+
test.verbose = true
|
41
|
+
end
|
42
|
+
|
43
|
+
require 'reek/rake/task'
|
44
|
+
Reek::Rake::Task.new do |t|
|
45
|
+
t.fail_on_error = true
|
46
|
+
t.verbose = false
|
47
|
+
t.source_files = 'lib/**/*.rb'
|
48
|
+
end
|
49
|
+
|
50
|
+
require 'roodi'
|
51
|
+
require 'roodi_task'
|
52
|
+
RoodiTask.new do |t|
|
53
|
+
t.verbose = false
|
54
|
+
end
|
55
|
+
|
56
|
+
task :default => :test
|
57
|
+
|
58
|
+
require 'rake/rdoctask'
|
59
|
+
Rake::RDocTask.new do |rdoc|
|
60
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
61
|
+
|
62
|
+
rdoc.rdoc_dir = 'rdoc'
|
63
|
+
rdoc.title = "mead #{version}"
|
64
|
+
rdoc.rdoc_files.include('README*')
|
65
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
66
|
+
end
|
67
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.5
|
data/bin/automead
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
require 'pp'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'mead'
|
6
|
+
require 'mead/trollop'
|
7
|
+
require 'trollop'
|
8
|
+
include Mead::TrollopOptions
|
9
|
+
|
10
|
+
opts = Trollop::options do
|
11
|
+
banner <<-EOS
|
12
|
+
This script takes a mead (an identifier of a particular format) and returns
|
13
|
+
metadata for it.
|
14
|
+
|
15
|
+
Usage Example:
|
16
|
+
automead --mead mc00240-001-ff0052-000-001 --baseurl http://www.lib.ncsu.edu/findingaids --ruby [options]
|
17
|
+
|
18
|
+
Default output is pretty printed Ruby. Multiple outputs can be specified.
|
19
|
+
|
20
|
+
where options are:
|
21
|
+
EOS
|
22
|
+
opt :mead, "A mead-style identifier", :required => true, :type => String
|
23
|
+
opt :baseurl, 'Specify just the base URL for grabbing the EAD XML if it is of the format baseurl/eadid.xml.', :type => String
|
24
|
+
opt :url, 'Specify the whole URL for grabbing the EAD XML.', :type => String
|
25
|
+
opt :file, 'File path to EAD XML.', :type => String
|
26
|
+
opt :ruby, 'Output as pretty printed Ruby. Default.'
|
27
|
+
opt :json, 'Output as JSON'
|
28
|
+
end
|
29
|
+
|
30
|
+
check_options(opts)
|
31
|
+
location = get_location(opts)
|
32
|
+
|
33
|
+
mead = Mead::Identifier.new(opts[:mead], location)
|
34
|
+
|
35
|
+
if mead.valid?
|
36
|
+
pp mead.metadata if opts[:ruby]
|
37
|
+
puts mead.metadata.to_json if opts[:json]
|
38
|
+
if !opts[:ruby] and !opts[:json]
|
39
|
+
pp mead.metadata
|
40
|
+
end
|
41
|
+
else
|
42
|
+
response = {}
|
43
|
+
response[:status] = 'Invalid'
|
44
|
+
response.merge!(mead.errors)
|
45
|
+
pp response if opts[:ruby]
|
46
|
+
if opts[:json]
|
47
|
+
response[:mead] = response[:mead].map{|error| error.message }
|
48
|
+
puts response.to_json
|
49
|
+
end
|
50
|
+
if !opts[:ruby] and !opts[:json]
|
51
|
+
pp response
|
52
|
+
end
|
53
|
+
end
|
data/bin/ead2meads
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
require 'pp'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'mead'
|
6
|
+
require 'json'
|
7
|
+
require 'mead/trollop'
|
8
|
+
require 'trollop'
|
9
|
+
include Mead::TrollopOptions
|
10
|
+
|
11
|
+
#eadid, baseurl
|
12
|
+
opts = Trollop::options do
|
13
|
+
banner <<-EOS
|
14
|
+
This script takes an EAD XML document and returns mead identifiers and metadata
|
15
|
+
for it. It is possible to validate whether the parsed EAD XML provides unique
|
16
|
+
identifiers for all component parts.
|
17
|
+
|
18
|
+
Usage Example:
|
19
|
+
ead2meads --url http://www.lib.ncsu.edu/findingaids/mc00240.xml [options]
|
20
|
+
|
21
|
+
Default output is pretty printed Ruby. Multiple outputs can be specified.
|
22
|
+
|
23
|
+
where options are:
|
24
|
+
EOS
|
25
|
+
opt :eadid, 'Eadid of the EAD.', :type => String
|
26
|
+
opt :url, 'Specify the whole URL for grabbing the EAD XML.', :type => String
|
27
|
+
opt :file, 'File path to EAD XML.', :type => String
|
28
|
+
opt :ruby, 'Output as pretty printed Ruby.'
|
29
|
+
opt :json, 'Output as JSON'
|
30
|
+
opt :csv, 'Output as CSV. Default.'
|
31
|
+
opt :valid, 'Only outputs whether the EAD creates valid identifiers or not.'
|
32
|
+
opt :verbose, 'Outputs the list of invalid containers in cases where invalid.'
|
33
|
+
opt :meadsonly, 'Only output a list of mead identifiers.'
|
34
|
+
end
|
35
|
+
|
36
|
+
check_options(opts)
|
37
|
+
location = get_location_options(opts)
|
38
|
+
|
39
|
+
options = {}
|
40
|
+
options[:eadid] = opts[:eadid] if opts[:eadid]
|
41
|
+
options.merge!(location)
|
42
|
+
|
43
|
+
begin
|
44
|
+
ead = Mead::Ead.new(options)
|
45
|
+
rescue => e
|
46
|
+
puts e
|
47
|
+
puts e.backtrace
|
48
|
+
exit
|
49
|
+
end
|
50
|
+
|
51
|
+
if opts[:valid]
|
52
|
+
if ead.valid?
|
53
|
+
puts 'Valid.'
|
54
|
+
else
|
55
|
+
if opts[:verbose]
|
56
|
+
puts Mead::Ead.to_csv(ead.invalid) if opts[:csv]
|
57
|
+
pp ead.invalid if opts[:ruby]
|
58
|
+
puts ead.invalid.to_json if opts[:json]
|
59
|
+
|
60
|
+
if !opts[:csv] and !opts[:ruby] and !opts[:json]
|
61
|
+
puts Mead::Ead.to_csv(ead.invalid)
|
62
|
+
end
|
63
|
+
else
|
64
|
+
if opts[:json]
|
65
|
+
json_output = {:dups => ead.dups.length, :invalid => ead.invalid.length, :total => ead.containers.length}.to_json
|
66
|
+
puts json_output
|
67
|
+
else
|
68
|
+
puts 'Invalid!'
|
69
|
+
puts 'Number of duplicate meads: ' + ead.dups.length.to_s
|
70
|
+
puts 'Effected Containers: ' + ead.invalid.length.to_s
|
71
|
+
puts 'Short meads:' + ead.short_meads.length.to_s
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
end
|
77
|
+
else
|
78
|
+
if opts[:meadsonly]
|
79
|
+
puts ead.meads.join("\n")
|
80
|
+
else
|
81
|
+
puts ead.to_csv if opts[:csv]
|
82
|
+
pp ead.containers if opts[:ruby]
|
83
|
+
puts ead.containers.to_json if opts[:json]
|
84
|
+
|
85
|
+
if !opts[:csv] and !opts[:ruby] and !opts[:json]
|
86
|
+
puts ead.to_csv
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
data/bin/emv
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'pp'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
# does an Mead::Ead validity check on a directory of EADs using the ead2meads tool
|
7
|
+
dir = ARGV[0] || (puts 'Give the path to a directory of EADs to validate!'; exit)
|
8
|
+
|
9
|
+
valid = []
|
10
|
+
invalid = []
|
11
|
+
invalid_responses = {}
|
12
|
+
|
13
|
+
files = Dir.glob(File.join(dir, '*.xml'))
|
14
|
+
puts files.length
|
15
|
+
files.each_with_index do |path, i|
|
16
|
+
begin
|
17
|
+
eadid = File.basename(path, '.xml')
|
18
|
+
cmd = File.join(File.dirname(__FILE__), 'ead2meads')
|
19
|
+
response = `#{cmd} --file #{path} --json --valid`.chomp
|
20
|
+
pp response
|
21
|
+
if response == 'Valid.'
|
22
|
+
puts i.to_s + ' ' + eadid + ': valid'
|
23
|
+
valid << eadid
|
24
|
+
elsif response.empty?
|
25
|
+
else
|
26
|
+
puts i.to_s + ' ' + eadid + ': !'
|
27
|
+
invalid << eadid
|
28
|
+
invalid_responses[eadid] = response
|
29
|
+
end
|
30
|
+
rescue => e
|
31
|
+
invalid_responses[eadid] = e.backtrace
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
puts 'Valid: ' + valid.length.to_s
|
36
|
+
puts 'Invalid: ' + invalid.length.to_s
|
37
|
+
|
38
|
+
puts 'Show all Invalid?'
|
39
|
+
answer = STDIN.gets
|
40
|
+
if answer.chomp == 'y'
|
41
|
+
pp invalid.sort
|
42
|
+
end
|
43
|
+
|
44
|
+
puts 'Show invalid responses?'
|
45
|
+
answer = STDIN.gets
|
46
|
+
if answer.chomp == 'y'
|
47
|
+
invalid_responses.each do |k,v|
|
48
|
+
puts k
|
49
|
+
puts v.sub("Invalid!\n", '')
|
50
|
+
puts
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
puts 'Show setdata?'
|
55
|
+
answer = STDIN.gets
|
56
|
+
if answer.chomp == 'y'
|
57
|
+
data = [%Q|google.load("visualization", "1", {packages:["corechart"]});
|
58
|
+
google.setOnLoadCallback(drawChart);
|
59
|
+
function drawChart() {
|
60
|
+
var data = new google.visualization.DataTable();","data.addColumn('string', 'eadid');|,
|
61
|
+
"data.addColumn('number', 'duplicates');",
|
62
|
+
"data.addColumn('number', 'invalid containers');"]
|
63
|
+
data << "data.addRows(#{invalid_responses.length});"
|
64
|
+
invalid_order = invalid_responses.keys.sort_by do |k|
|
65
|
+
invalid_response = JSON.parse(invalid_responses[k])
|
66
|
+
invalid_responses[k]["invalid"]
|
67
|
+
end
|
68
|
+
invalid_order.each_with_index do |key, i|
|
69
|
+
invalid_response = JSON.parse(invalid_responses[key])
|
70
|
+
|
71
|
+
data << "data.setValue(#{i}, 0, '#{key}');"
|
72
|
+
data << "data.setValue(#{i}, 1, #{invalid_response['dups']});"
|
73
|
+
data << "data.setValue(#{i}, 2, #{invalid_response['invalid']});"
|
74
|
+
end
|
75
|
+
puts data.join("\n")
|
76
|
+
end
|
77
|
+
|
data/bin/mead2barcode
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
require 'pp'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'mead'
|
6
|
+
require 'mead/trollop'
|
7
|
+
require 'trollop'
|
8
|
+
include Mead::TrollopOptions
|
9
|
+
|
10
|
+
opts = Trollop::options do
|
11
|
+
banner <<-EOS
|
12
|
+
This script takes a mead (an identifier of a particular format), creates a
|
13
|
+
barcode and returns the path to the barcode. Gbarcode and RMagick gems must be
|
14
|
+
installed for this to work.
|
15
|
+
|
16
|
+
Usage Example:
|
17
|
+
mead2barcode --mead mc00240-001-ff0052-000-001 --baseurl http://www.lib.ncsu.edu/findingaids --ruby [options]
|
18
|
+
|
19
|
+
where options are:
|
20
|
+
EOS
|
21
|
+
opt :mead, "A mead-style identifier", :type => String
|
22
|
+
opt :meadfile, "Path to text file with one mead identifier on each line.", :type => String
|
23
|
+
opt :baseurl, 'Specify just the base URL for grabbing the EAD XML if it is of the format baseurl/eadid.xml.', :type => String
|
24
|
+
opt :url, 'Specify the whole URL for grabbing the EAD XML.', :type => String
|
25
|
+
opt :file, 'File path to EAD XML.', :type => String
|
26
|
+
opt :dir, 'Directory to save the barcodes.', :type => String
|
27
|
+
end
|
28
|
+
|
29
|
+
unless opts[:mead] or opts[:meadfile]
|
30
|
+
Trollop::die 'You must specify either a single mead identifier or a file of identifiers'
|
31
|
+
end
|
32
|
+
|
33
|
+
check_options(opts)
|
34
|
+
location = get_location(opts)
|
35
|
+
|
36
|
+
if opts[:mead]
|
37
|
+
meads = [opts[:mead]]
|
38
|
+
else
|
39
|
+
Trollop::die 'meadfile must be a valid path' unless File.exists?(opts[:meadfile])
|
40
|
+
meads = File.open(opts[:meadfile], 'r').read.split
|
41
|
+
end
|
42
|
+
|
43
|
+
successful_paths = []
|
44
|
+
meads.each do |mead_identifier|
|
45
|
+
begin
|
46
|
+
mead = Mead::Identifier.new(mead_identifier, location).extract
|
47
|
+
|
48
|
+
barcode = Mead::Barcode.new(mead)
|
49
|
+
|
50
|
+
if opts[:dir]
|
51
|
+
Trollop::die 'Directory must exist!' unless File.exists?(opts[:dir])
|
52
|
+
end
|
53
|
+
directory = opts[:dir] || Dir.pwd
|
54
|
+
|
55
|
+
label_path = barcode.output_label(directory)
|
56
|
+
successful_paths << label_path
|
57
|
+
puts label_path
|
58
|
+
rescue => e
|
59
|
+
puts mead_identifier + ' ' + e
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
#`convert #{successful_paths.join(' ')} -append -antialias output.png`
|
64
|
+
|
data/bin/meadbfv
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
require 'pp'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'mead'
|
6
|
+
require 'pp'
|
7
|
+
|
8
|
+
|
9
|
+
file = ARGV[0]
|
10
|
+
|
11
|
+
filenames = File.read(file).split
|
12
|
+
|
13
|
+
valid = []
|
14
|
+
invalid = []
|
15
|
+
filenames.each do |filename|
|
16
|
+
mead = Mead::Identifier.new(filename)
|
17
|
+
if mead.valid_format?
|
18
|
+
valid << filename
|
19
|
+
else
|
20
|
+
invalid << filename
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
puts "Total filenames " + filenames.length.to_s
|
25
|
+
puts "Unique filenames " + filenames.uniq.length.to_s
|
26
|
+
puts "Valid filenames " + valid.length.to_s unless valid.empty?
|
27
|
+
puts "Invalid filenames " + invalid.length.to_s unless invalid.empty?
|
data/lib/mead/barcode.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
module Mead
|
2
|
+
class Barcode
|
3
|
+
attr_accessor :mead
|
4
|
+
|
5
|
+
def initialize(identifier)
|
6
|
+
@mead = identifier
|
7
|
+
end
|
8
|
+
|
9
|
+
def output_barcode(directory)
|
10
|
+
bc = Gbarcode.barcode_create(@mead.mead)
|
11
|
+
bc.scalef = 0.5
|
12
|
+
bc.margin = 25
|
13
|
+
Gbarcode.barcode_encode(bc, Gbarcode::BARCODE_128)
|
14
|
+
#tempfile for eps version of barcode
|
15
|
+
eps_path = File.join(directory, @mead.mead + '.eps')
|
16
|
+
png_path = File.join(directory, @mead.mead + '-barcode.png')
|
17
|
+
eps = File.new(eps_path, 'w')
|
18
|
+
Gbarcode.barcode_print(bc, eps, Gbarcode::BARCODE_OUT_EPS)
|
19
|
+
eps.close
|
20
|
+
`convert +antialias #{eps_path} -background white -flatten #{png_path}`
|
21
|
+
File.delete(eps_path)
|
22
|
+
png_path
|
23
|
+
end
|
24
|
+
|
25
|
+
def output_label(directory)
|
26
|
+
text_path = File.join(directory, @mead.mead + '-text.png')
|
27
|
+
label_path = File.join(directory, @mead.mead + '-label.png')
|
28
|
+
`convert -font fixed -pointsize 14 -background white -fill black label:"#{label_text}" #{text_path}`
|
29
|
+
# convert *.png -resize 75% -append output.png
|
30
|
+
png_path = output_barcode(directory)
|
31
|
+
begin
|
32
|
+
`convert #{png_path} #{text_path} -append #{label_path}`
|
33
|
+
rescue
|
34
|
+
end
|
35
|
+
File.delete(png_path)
|
36
|
+
File.delete(text_path)
|
37
|
+
label_path
|
38
|
+
end
|
39
|
+
|
40
|
+
def label_text
|
41
|
+
text = [@mead.mead]
|
42
|
+
text << @mead.metadata.first[:unittitle][0,55]
|
43
|
+
text.last << '...' if @mead.metadata.first[:unittitle].length > 55
|
44
|
+
text << @mead.metadata.first[:item_location]
|
45
|
+
text.join('\n')
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Mead
|
2
|
+
class Container
|
3
|
+
attr_accessor :identifier, :type, :label, :text
|
4
|
+
|
5
|
+
def initialize(options={})
|
6
|
+
@type = options[:type]
|
7
|
+
@label = options[:label]
|
8
|
+
@identifier = options[:identifier]
|
9
|
+
@text = options[:text]
|
10
|
+
end
|
11
|
+
|
12
|
+
def ==(another_container)
|
13
|
+
self.identifier == another_container.identifier and
|
14
|
+
self.type == another_container.type and
|
15
|
+
self.label == another_container.label and
|
16
|
+
self.text == another_container.text
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|