rof 1.0.7 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +9 -7
  3. data/LICENSE +201 -16
  4. data/Rakefile +46 -0
  5. data/bin/csv_to_rof +1 -2
  6. data/bin/fedora_to_rof +7 -1
  7. data/bin/jsonld_to_rof +26 -0
  8. data/bin/osf_to_rof +6 -2
  9. data/bin/rof +5 -19
  10. data/lib/rof.rb +2 -6
  11. data/lib/rof/access.rb +1 -1
  12. data/lib/rof/cli.rb +104 -67
  13. data/lib/rof/compare_rof.rb +68 -39
  14. data/lib/rof/filter.rb +21 -0
  15. data/lib/rof/filters.rb +38 -0
  16. data/lib/rof/filters/bendo.rb +15 -17
  17. data/lib/rof/filters/date_stamp.rb +5 -4
  18. data/lib/rof/filters/file_to_url.rb +5 -3
  19. data/lib/rof/filters/label.rb +9 -7
  20. data/lib/rof/filters/work.rb +7 -5
  21. data/lib/rof/ingest.rb +5 -0
  22. data/lib/rof/osf_context.rb +2 -2
  23. data/lib/rof/rdf_context.rb +2 -0
  24. data/lib/rof/translator.rb +18 -0
  25. data/lib/rof/translators.rb +23 -0
  26. data/lib/rof/{translate_csv.rb → translators/csv_to_rof.rb} +4 -3
  27. data/lib/rof/translators/fedora_to_rof.rb +244 -0
  28. data/lib/rof/translators/jsonld_to_rof.rb +112 -0
  29. data/lib/rof/translators/jsonld_to_rof/accumulator.rb +175 -0
  30. data/lib/rof/translators/jsonld_to_rof/predicate_handler.rb +223 -0
  31. data/lib/rof/translators/jsonld_to_rof/predicate_object_handler.rb +125 -0
  32. data/lib/rof/translators/jsonld_to_rof/statement_handler.rb +91 -0
  33. data/lib/rof/translators/osf_to_rof.rb +191 -0
  34. data/lib/rof/utility.rb +44 -1
  35. data/lib/rof/version.rb +1 -1
  36. data/rof.gemspec +10 -2
  37. data/spec/coverage_helper.rb +17 -0
  38. data/spec/fixtures/for_utility_load_items_from_json_file/multiple_items.json +8 -0
  39. data/spec/fixtures/for_utility_load_items_from_json_file/parse_error.json +3 -0
  40. data/spec/fixtures/for_utility_load_items_from_json_file/single_item.json +3 -0
  41. data/spec/fixtures/jsonld_to_rof/0g354f18610.jsonld +113 -0
  42. data/spec/fixtures/jsonld_to_rof/0g354f18610.rof +96 -0
  43. data/spec/fixtures/jsonld_to_rof/2j62s467216.jsonld +113 -0
  44. data/spec/fixtures/jsonld_to_rof/2j62s467216.rof +93 -0
  45. data/spec/fixtures/jsonld_to_rof/2v23vt16z2z.jsonld +70 -0
  46. data/spec/fixtures/jsonld_to_rof/2v23vt16z2z.rof +87 -0
  47. data/spec/fixtures/jsonld_to_rof/cr56n01253w.jsonld +84 -0
  48. data/spec/fixtures/jsonld_to_rof/cr56n01253w.rof +95 -0
  49. data/spec/fixtures/jsonld_to_rof/h989r21069m.jsonld +84 -0
  50. data/spec/fixtures/jsonld_to_rof/h989r21069m.rof +98 -0
  51. data/spec/fixtures/jsonld_to_rof/js956d59913.jsonld +79 -0
  52. data/spec/fixtures/jsonld_to_rof/js956d59913.rof +89 -0
  53. data/spec/fixtures/jsonld_to_rof/m039k358q5c.jsonld +80 -0
  54. data/spec/fixtures/jsonld_to_rof/m039k358q5c.rof +64 -0
  55. data/spec/fixtures/jsonld_to_rof/nk322b9161g.jsonld +89 -0
  56. data/spec/fixtures/jsonld_to_rof/nk322b9161g.rof +69 -0
  57. data/spec/fixtures/jsonld_to_rof/p8418k7430d.jsonld +84 -0
  58. data/spec/fixtures/jsonld_to_rof/p8418k7430d.rof +67 -0
  59. data/spec/fixtures/jsonld_to_rof/xg94hm53h0c.jsonld +98 -0
  60. data/spec/fixtures/jsonld_to_rof/xg94hm53h0c.rof +110 -0
  61. data/spec/fixtures/jsonld_to_rof/zk51vd69n1r.jsonld +94 -0
  62. data/spec/fixtures/jsonld_to_rof/zk51vd69n1r.rof +121 -0
  63. data/spec/fixtures/osf/phz6b.tar.gz +0 -0
  64. data/spec/lib/rof/access_spec.rb +30 -23
  65. data/spec/lib/rof/cli_spec.rb +83 -60
  66. data/spec/lib/rof/compare_rof_spec.rb +35 -24
  67. data/spec/lib/rof/filter_spec.rb +10 -0
  68. data/spec/lib/rof/filters/bendo_spec.rb +42 -0
  69. data/spec/lib/rof/filters/date_stamp_spec.rb +9 -5
  70. data/spec/lib/rof/filters/file_to_url_spec.rb +7 -3
  71. data/spec/lib/rof/filters/label_spec.rb +121 -77
  72. data/spec/lib/rof/filters/work_spec.rb +7 -4
  73. data/spec/lib/rof/filters_spec.rb +14 -0
  74. data/spec/lib/rof/translator_spec.rb +15 -0
  75. data/spec/lib/rof/{translate_csv_spec.rb → translators/csv_to_rof_spec.rb} +14 -14
  76. data/spec/lib/rof/translators/fedora_to_rof_spec.rb +64 -0
  77. data/spec/lib/rof/translators/jsonld_to_rof/accumulator_spec.rb +121 -0
  78. data/spec/lib/rof/translators/jsonld_to_rof/predicate_handler_spec.rb +73 -0
  79. data/spec/lib/rof/translators/jsonld_to_rof/predicate_object_handler_spec.rb +48 -0
  80. data/spec/lib/rof/translators/jsonld_to_rof/statement_handler_spec.rb +40 -0
  81. data/spec/lib/rof/translators/jsonld_to_rof_spec.rb +120 -0
  82. data/spec/lib/rof/{osf_to_rof_spec.rb → translators/osf_to_rof_spec.rb} +55 -25
  83. data/spec/lib/rof/translators_spec.rb +14 -0
  84. data/spec/lib/rof/utility_spec.rb +47 -1
  85. data/spec/spec_helper.rb +1 -1
  86. data/spec/support/an_rof_filter.rb +10 -0
  87. metadata +186 -15
  88. data/lib/rof/get_from_fedora.rb +0 -211
  89. data/lib/rof/osf_to_rof.rb +0 -123
  90. data/spec/lib/rof/get_from_fedora_spec.rb +0 -22
@@ -1,5 +1,6 @@
1
1
  require 'mime-types'
2
2
  require 'zlib'
3
+ require 'rsolr'
3
4
  require 'rubygems/package'
4
5
 
5
6
  module ROF
@@ -63,13 +64,55 @@ module ROF
63
64
  s
64
65
  end
65
66
 
67
+ # test for embargo xml cases
68
+ def self.has_embargo_date?(embargo_xml)
69
+ return false if embargo_xml == '' || embargo_xml.nil?
70
+ return false unless embargo_xml.elements['machine'].has_elements? && embargo_xml.elements['machine'].elements['date'].has_text?
71
+ true
72
+ end
73
+
74
+ # @api public
75
+ # @param fname [String] Path to filename
76
+ # @param outfile [#puts] Where to write exceptions
77
+ # @return [Array] The items in the JSON document, coerced into an Array (if a single item was encountered)
78
+ def self.load_items_from_json_file(fname, outfile = STDERR)
79
+ items = nil
80
+ File.open(fname, 'r:UTF-8') do |f|
81
+ items = JSON.parse(f.read)
82
+ end
83
+ items = [items] unless items.is_a? Array
84
+ items
85
+ rescue JSON::ParserError => e
86
+ outfile.puts("Error reading #{fname}:#{e}")
87
+ exit!(1)
88
+ end
89
+
90
+ # query SOLR for Previous version of OSF Project.
91
+ # Return its fedora pid if it is found, nil otherwise
92
+ def self.check_solr_for_previous(config, osf_project_identifier)
93
+ solr_url = config.fetch('solr_url', nil)
94
+ return nil if solr_url.nil?
95
+ solr = RSolr.connect url: "#{solr_url}/curatend"
96
+ query = solr.get 'select', params: {
97
+ q: "desc_metadata__osf_project_identifier_ssi:#{osf_project_identifier}",
98
+ rows: 1,
99
+ sort_by: 'date_archived',
100
+ fl: ['id'],
101
+ wt: 'json'
102
+ }
103
+ return nil if (query['response']['numFound']).zero?
104
+ # should only be 1 SOLR doc (the most recent) in docs[0]
105
+ query['response']['docs'][0]['id']
106
+ end
107
+
66
108
  # read file from gzipped tar archive
67
109
  def self.file_from_targz(targzfile, file_name)
68
110
  File.open(targzfile, 'rb') do |file|
69
111
  Zlib::GzipReader.wrap(file) do |gz|
70
112
  Gem::Package::TarReader.new(gz) do |tar|
71
113
  tar.seek(file_name) do |file_entry|
72
- file_dest_dir = File.join(File.dirname(targzfile), File.dirname(file_entry.full_name))
114
+ file_dest_dir = File.join(File.dirname(targzfile),
115
+ File.dirname(file_entry.full_name))
73
116
  FileUtils.mkdir_p(file_dest_dir)
74
117
  File.open(File.join(file_dest_dir, File.basename(file_name)), 'wb') do |file_handle|
75
118
  file_handle.write(file_entry.read)
@@ -1,3 +1,3 @@
1
1
  module ROF
2
- VERSION="1.0.7"
2
+ VERSION="1.2.0"
3
3
  end
@@ -22,22 +22,30 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.add_dependency "rdf", "~> 2.0.1"
24
24
  spec.add_dependency "rdf-rdfxml"
25
- spec.add_dependency "rdf-turtle"
25
+ # constrain rdf-turtle since the newer version wants rdf 2.2
26
+ spec.add_dependency "rdf-turtle", '~> 2.0.0'
26
27
  spec.add_dependency "rdf-isomorphic"
27
28
  spec.add_dependency "json-ld", "~> 2.0.0"
28
29
  spec.add_dependency "mime-types", "~> 2.4"
29
30
  spec.add_dependency "rubydora", "~> 1.8.1"
30
31
  spec.add_dependency "noids_client"
32
+ spec.add_dependency "rsolr"
31
33
  spec.add_dependency 'deprecation', '~> 0.1'
34
+ spec.add_dependency 'nokogiri', '~> 1.6.8.1' # Need this version for older rubies
32
35
  # only needed because we use ruby < 2.2.2 in production and that doesn't play
33
36
  # nice with rails 5
34
37
  spec.add_dependency 'activesupport', '< 5.0'
35
- spec.add_dependency 'ebnf', '< 1.0.2'
38
+ spec.add_dependency 'ebnf', '< 1.0.2'
39
+ # adding this only because bundler selects version 2.1 and it breaks things
40
+ spec.add_dependency 'rdf-xsd', '~> 2.0.0'
36
41
 
37
42
  spec.add_development_dependency "bundler", "~> 1.3"
43
+ spec.add_development_dependency "codeclimate-test-reporter"
44
+ spec.add_development_dependency "fasterer"
38
45
  spec.add_development_dependency "rake"
39
46
  spec.add_development_dependency 'rspec'
40
47
  spec.add_development_dependency 'rspec-its'
48
+ spec.add_development_dependency "simplecov"
41
49
  spec.add_development_dependency 'vcr'
42
50
  spec.add_development_dependency 'webmock'
43
51
  spec.add_development_dependency 'equivalent-xml'
@@ -0,0 +1,17 @@
1
+ ## Generation Notes:
2
+ ## This file was generated via the commitment:install generator. You are free
3
+ ## and expected to change this file.
4
+ if ENV['COV'] || ENV['COVERAGE'] || ENV['TRAVIS']
5
+ if ENV['TRAVIS']
6
+ require 'simplecov'
7
+ require "codeclimate-test-reporter"
8
+ SimpleCov.start do
9
+ formatter(
10
+ SimpleCov::Formatter::MultiFormatter.new([SimpleCov::Formatter::HTMLFormatter, CodeClimate::TestReporter::Formatter])
11
+ )
12
+ end
13
+ elsif ENV['COV'] || ENV['COVERAGE']
14
+ require 'simplecov'
15
+ SimpleCov.start
16
+ end
17
+ end
@@ -0,0 +1,8 @@
1
+ [
2
+ {
3
+ "hello": "world"
4
+ },
5
+ {
6
+ "good": "bye"
7
+ }
8
+ ]
@@ -0,0 +1,113 @@
1
+ {
2
+ "@context": {
3
+ "und": "https://curate.nd.edu/show/",
4
+ "bibo": "http://purl.org/ontology/bibo/",
5
+ "dc": "http://purl.org/dc/terms/",
6
+ "ebucore": "http://www.ebu.ch/metadata/ontologies/ebucore/ebucore#",
7
+ "foaf": "http://xmlns.com/foaf/0.1/",
8
+ "mrel": "http://id.loc.gov/vocabulary/relators/",
9
+ "nd": "https://library.nd.edu/ns/terms/",
10
+ "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
11
+ "vracore": "http://purl.org/vra/",
12
+ "frels": "info:fedora/fedora-system:def/relations-external#",
13
+ "ms": "http://www.ndltd.org/standards/metadata/etdms/1.1/",
14
+ "pav": "http://purl.org/pav/",
15
+ "fedora-model": "info:fedora/fedora-system:def/model#",
16
+ "hydra": "http://projecthydra.org/ns/relations#",
17
+ "hasModel": {
18
+ "@id": "fedora-model:hasModel",
19
+ "@type": "@id"
20
+ },
21
+ "hasEditor": {
22
+ "@id": "hydra:hasEditor",
23
+ "@type": "@id"
24
+ },
25
+ "hasEditorGroup": {
26
+ "@id": "hydra:hasEditorGroup",
27
+ "@type": "@id"
28
+ },
29
+ "isPartOf": {
30
+ "@id": "frels:isPartOf",
31
+ "@type": "@id"
32
+ },
33
+ "isMemberOfCollection": {
34
+ "@id": "frels:isMemberOfCollection",
35
+ "@type": "@id"
36
+ },
37
+ "isEditorOf": {
38
+ "@id": "hydra:isEditorOf",
39
+ "@type": "@id"
40
+ },
41
+ "hasMember": {
42
+ "@id": "frels:hasMember",
43
+ "@type": "@id"
44
+ },
45
+ "previousVersion": "pav:previousVersion"
46
+ },
47
+ "@graph": [{
48
+ "@id": "_:b0",
49
+ "dc:contributor": "Maura Ryan",
50
+ "ms:role": "Research Director"
51
+ }, {
52
+ "@id": "_:b1",
53
+ "dc:contributor": "Jean Porter",
54
+ "ms:role": "Committee Member"
55
+ }, {
56
+ "@id": "_:b2",
57
+ "dc:contributor": "David Clairmont",
58
+ "ms:role": "Committee Member"
59
+ }, {
60
+ "@id": "_:b3",
61
+ "dc:contributor": "Andrew S. Park",
62
+ "ms:role": "Committee Member"
63
+ }, {
64
+ "@id": "_:b4",
65
+ "ms:discipline": ["Philosophy"],
66
+ "ms:level": "Doctoral Dissertation",
67
+ "ms:name": "Doctor of Philosophy"
68
+ }, {
69
+ "@id": "und:0g354f18610",
70
+ "dc:contributor": [{
71
+ "@id": "_:b0"
72
+ }, {
73
+ "@id": "_:b1"
74
+ }, {
75
+ "@id": "_:b2"
76
+ }, {
77
+ "@id": "_:b3"
78
+ }],
79
+ "dc:creator": "Joungeun Lee",
80
+ "dc:date": "2015-06-29",
81
+ "dc:date#created": "",
82
+ "dc:dateSubmitted": "2016-02-18Z",
83
+ "dc:description#abstract": "<p>The goal of this dissertation is to bring together in conversation Aquinas's thoughts on anger and the <i>han</i> (恨)-full anger as a culture-bound syndrome in South Korean people and society, and to make a constructive proposal for working with the anger of the <i>han</i>-filled. Aquinas' ontological cognitivist theory of passion and anger in particular provides a useful hermeneutical tool to analyze and articulate the inner structure of <i>han</i>-full anger and its moral character. The study of <i>han</i>-full anger offers Aquinas’s normative language of anger a chance to encounter the etymological and phenomenological reality of embodied anger and further the life of its bearer living in a marginalized life. Finally, Aquinas’s virtue ethics, taken together with <i>han</i> studies, suggests a modified way to work with the <i>han</i>-full anger. </p>",
84
+ "dc:description#note": "",
85
+ "dc:identifier#other": "",
86
+ "dc:modified": {
87
+ "@value": "2016-02-19Z",
88
+ "@type": "http://www.w3.org/2001/XMLSchema#date"
89
+ },
90
+ "dc:publisher#country": "",
91
+ "dc:rights": "All rights reserved",
92
+ "dc:title": "Anger in Thomas Aquinas and <i>Han</i>-full Anger",
93
+ "dc:title#alternate": "",
94
+ "hydra:hasEditor": {
95
+ "@id": "und:qb98mc9021z"
96
+ },
97
+ "hydra:hasEditorGroup": {
98
+ "@id": "und:q524jm23g92"
99
+ },
100
+ "ms:degree": {
101
+ "@id": "_:b4"
102
+ },
103
+ "nd:accessEdit": "curate_batch_user",
104
+ "nd:accessEmbargoDate": "2016-02-28",
105
+ "nd:accessRead": "jlee20",
106
+ "nd:accessReadGroup": "public",
107
+ "nd:afmodel": "Etd",
108
+ "nd:depositor": "curate_batch_user",
109
+ "nd:representativeFile": {
110
+ "@id": "und:rv042r3997b"
111
+ }
112
+ }]
113
+ }
@@ -0,0 +1,96 @@
1
+ [
2
+ {
3
+ "type": "fobject",
4
+ "pid": "und:0g354f18610",
5
+ "af-model": "Etd",
6
+ "rights": {
7
+ "read": [
8
+ "jlee20"
9
+ ],
10
+ "edit": [
11
+ "curate_batch_user"
12
+ ],
13
+ "read-groups": [
14
+ "public"
15
+ ],
16
+ "embargo-date": "2016-02-28",
17
+ "edit-groups": [
18
+ "und:q524jm23g92"
19
+ ]
20
+ },
21
+ "metadata": {
22
+ "@context": {
23
+ "dc": "http://purl.org/dc/terms/",
24
+ "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
25
+ "ms": "http://www.ndltd.org/standards/metadata/etdms/1.1/",
26
+ "ths": "http://id.loc.gov/vocabulary/relators/"
27
+ },
28
+ "dc:title#alternate": [
29
+
30
+ ],
31
+ "dc:subject": [
32
+
33
+ ],
34
+ "dc:description#abstract": [
35
+ "<p>The goal of this dissertation is to bring together in conversation Aquinas's thoughts on anger and the <i>han</i> (恨)-full anger as a culture-bound syndrome in South Korean people and society, and to make a constructive proposal for working with the anger of the <i>han</i>-filled. Aquinas' ontological cognitivist theory of passion and anger in particular provides a useful hermeneutical tool to analyze and articulate the inner structure of <i>han</i>-full anger and its moral character. The study of <i>han</i>-full anger offers Aquinas’s normative language of anger a chance to encounter the etymological and phenomenological reality of embodied anger and further the life of its bearer living in a marginalized life. Finally, Aquinas’s virtue ethics, taken together with <i>han</i> studies, suggests a modified way to work with the <i>han</i>-full anger. </p>"
36
+ ],
37
+ "dc:rights": [
38
+ "All rights reserved"
39
+ ],
40
+ "dc:language": [
41
+
42
+ ],
43
+ "dc:date": [
44
+ "2015-06-29"
45
+ ],
46
+ "dc:title": "Anger in Thomas Aquinas and <i>Han</i>-full Anger",
47
+ "dc:contributor": [
48
+ {
49
+ "dc:contributor": "Maura Ryan",
50
+ "ms:role": "Research Director"
51
+ },
52
+ {
53
+ "dc:contributor": "Jean Porter",
54
+ "ms:role": "Committee Member"
55
+ },
56
+ {
57
+ "dc:contributor": "David Clairmont",
58
+ "ms:role": "Committee Member"
59
+ },
60
+ {
61
+ "dc:contributor": "Andrew S. Park",
62
+ "ms:role": "Committee Member"
63
+ }
64
+ ],
65
+ "ms:degree": {
66
+ "ms:name": [
67
+ "Doctor of Philosophy"
68
+ ],
69
+ "ms:discipline": [
70
+ "Philosophy"
71
+ ],
72
+ "ms:level": "Doctoral Dissertation"
73
+ },
74
+ "dc:creator": [
75
+ "Joungeun Lee"
76
+ ],
77
+ "dc:dateSubmitted": "2016-02-18Z",
78
+ "dc:modified": "2016-02-19Z"
79
+ },
80
+ "rels-ext": {
81
+ "@context": {
82
+ "hydramata-rel": "http://projecthydra.org/ns/relations#"
83
+ },
84
+ "hydramata-rel:hasEditor": [
85
+ "und:qb98mc9021z"
86
+ ],
87
+ "hydramata-rel:hasEditorGroup": [
88
+ "und:q524jm23g92"
89
+ ]
90
+ },
91
+ "properties-meta": {
92
+ "mime-type": "text/xml"
93
+ },
94
+ "properties": "<fields><depositor>curate_batch_user</depositor><representative>und:rv042r3997b</representative></fields>"
95
+ }
96
+ ]
@@ -0,0 +1,113 @@
1
+ {
2
+ "@context": {
3
+ "und": "https://curate.nd.edu/show/",
4
+ "bibo": "http://purl.org/ontology/bibo/",
5
+ "dc": "http://purl.org/dc/terms/",
6
+ "ebucore": "http://www.ebu.ch/metadata/ontologies/ebucore/ebucore#",
7
+ "foaf": "http://xmlns.com/foaf/0.1/",
8
+ "mrel": "http://id.loc.gov/vocabulary/relators/",
9
+ "nd": "https://library.nd.edu/ns/terms/",
10
+ "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
11
+ "vracore": "http://purl.org/vra/",
12
+ "frels": "info:fedora/fedora-system:def/relations-external#",
13
+ "ms": "http://www.ndltd.org/standards/metadata/etdms/1.1/",
14
+ "pav": "http://purl.org/pav/",
15
+ "fedora-model": "info:fedora/fedora-system:def/model#",
16
+ "hydra": "http://projecthydra.org/ns/relations#",
17
+ "hasModel": {
18
+ "@id": "fedora-model:hasModel",
19
+ "@type": "@id"
20
+ },
21
+ "hasEditor": {
22
+ "@id": "hydra:hasEditor",
23
+ "@type": "@id"
24
+ },
25
+ "hasEditorGroup": {
26
+ "@id": "hydra:hasEditorGroup",
27
+ "@type": "@id"
28
+ },
29
+ "isPartOf": {
30
+ "@id": "frels:isPartOf",
31
+ "@type": "@id"
32
+ },
33
+ "isMemberOfCollection": {
34
+ "@id": "frels:isMemberOfCollection",
35
+ "@type": "@id"
36
+ },
37
+ "isEditorOf": {
38
+ "@id": "hydra:isEditorOf",
39
+ "@type": "@id"
40
+ },
41
+ "hasMember": {
42
+ "@id": "frels:hasMember",
43
+ "@type": "@id"
44
+ },
45
+ "previousVersion": "pav:previousVersion"
46
+ },
47
+ "@graph": [{
48
+ "@id": "_:b0",
49
+ "dc:contributor": "Brad S. Gregory",
50
+ "ms:role": "Research Director"
51
+ }, {
52
+ "@id": "_:b1",
53
+ "dc:contributor": "John Van Engen",
54
+ "ms:role": "Committee Member"
55
+ }, {
56
+ "@id": "_:b2",
57
+ "dc:contributor": "Margaret Meserve",
58
+ "ms:role": "Committee Member"
59
+ }, {
60
+ "@id": "_:b3",
61
+ "dc:contributor": "Thomas Kselman",
62
+ "ms:role": "Committee Member"
63
+ }, {
64
+ "@id": "_:b4",
65
+ "ms:discipline": ["History"],
66
+ "ms:level": "Doctoral Dissertation",
67
+ "ms:name": "Doctor of Philosophy"
68
+ }, {
69
+ "@id": "und:2j62s467216",
70
+ "dc:contributor": [{
71
+ "@id": "_:b0"
72
+ }, {
73
+ "@id": "_:b1"
74
+ }, {
75
+ "@id": "_:b2"
76
+ }, {
77
+ "@id": "_:b3"
78
+ }],
79
+ "dc:creator": "Christopher J. Lane",
80
+ "dc:date": "2015-06-10",
81
+ "dc:date#approved": "",
82
+ "dc:date#created": "",
83
+ "dc:dateSubmitted": "2016-02-18Z",
84
+ "dc:description#note": "",
85
+ "dc:identifier#other": "",
86
+ "dc:modified": {
87
+ "@value": "2016-02-19Z",
88
+ "@type": "http://www.w3.org/2001/XMLSchema#date"
89
+ },
90
+ "dc:publisher#country": "",
91
+ "dc:rights": "All rights reserved",
92
+ "dc:title": "The Diversity of Vocations: Choosing a State of Life in Early Modern France",
93
+ "dc:title#alternate": "",
94
+ "hydra:hasEditor": {
95
+ "@id": "und:qb98mc9021z"
96
+ },
97
+ "hydra:hasEditorGroup": {
98
+ "@id": "und:q524jm23g92"
99
+ },
100
+ "ms:degree": {
101
+ "@id": "_:b4"
102
+ },
103
+ "nd:accessEmbargoDate": "2021-12-31",
104
+ "nd:accessEdit": "curate_batch_user",
105
+ "nd:accessRead": "clane",
106
+ "nd:accessReadGroup": "public",
107
+ "nd:afmodel": "Etd",
108
+ "nd:depositor": "curate_batch_user",
109
+ "nd:representativeFile": {
110
+ "@id": "und:47429882s8w"
111
+ }
112
+ }]
113
+ }