puree 0.20.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -2
  3. data/PITCHME.md +43 -21
  4. data/README.md +72 -18
  5. data/lib/puree.rb +66 -21
  6. data/lib/puree/api/api.rb +9 -0
  7. data/lib/puree/api/authentication.rb +33 -0
  8. data/lib/puree/api/configuration.rb +43 -0
  9. data/lib/puree/api/map.rb +76 -0
  10. data/lib/puree/api/request.rb +116 -0
  11. data/lib/puree/extractor/collection.rb +131 -0
  12. data/lib/puree/extractor/dataset.rb +48 -0
  13. data/lib/puree/extractor/download.rb +71 -0
  14. data/lib/puree/extractor/event.rb +33 -0
  15. data/lib/puree/extractor/extractor.rb +10 -0
  16. data/lib/puree/extractor/journal.rb +29 -0
  17. data/lib/puree/extractor/organisation.rb +34 -0
  18. data/lib/puree/extractor/person.rb +32 -0
  19. data/lib/puree/extractor/project.rb +40 -0
  20. data/lib/puree/extractor/publication.rb +40 -0
  21. data/lib/puree/extractor/publisher.rb +27 -0
  22. data/lib/puree/extractor/resource.rb +69 -0
  23. data/lib/puree/extractor/server.rb +56 -0
  24. data/lib/puree/model/address.rb +50 -0
  25. data/lib/puree/model/copyright_license.rb +26 -0
  26. data/lib/puree/model/dataset.rb +84 -0
  27. data/lib/puree/model/download_header.rb +21 -0
  28. data/lib/puree/model/endeavour_person.rb +34 -0
  29. data/lib/puree/model/event.rb +31 -0
  30. data/lib/puree/model/event_header.rb +26 -0
  31. data/lib/puree/model/file.rb +45 -0
  32. data/lib/puree/model/helper/validation.rb +15 -0
  33. data/lib/puree/model/journal.rb +20 -0
  34. data/lib/puree/model/legal_condition.rb +26 -0
  35. data/lib/puree/model/link.rb +26 -0
  36. data/lib/puree/model/model.rb +7 -0
  37. data/lib/puree/model/organisation.rb +34 -0
  38. data/lib/puree/model/organisation_header.rb +34 -0
  39. data/lib/puree/model/person.rb +28 -0
  40. data/lib/puree/model/person_name.rb +52 -0
  41. data/lib/puree/model/project.rb +49 -0
  42. data/lib/puree/model/publication.rb +53 -0
  43. data/lib/puree/model/publication_status.rb +21 -0
  44. data/lib/puree/model/publisher.rb +13 -0
  45. data/lib/puree/model/related_content_header.rb +34 -0
  46. data/lib/puree/model/resource.rb +42 -0
  47. data/lib/puree/model/server.rb +13 -0
  48. data/lib/puree/model/spatial_point.rb +16 -0
  49. data/lib/puree/model/structure.rb +18 -0
  50. data/lib/puree/model/temporal_range.rb +15 -0
  51. data/lib/puree/util/date.rb +86 -0
  52. data/lib/puree/util/util.rb +8 -0
  53. data/lib/puree/version.rb +1 -1
  54. data/lib/puree/xml_extractor/base.rb +47 -0
  55. data/lib/puree/xml_extractor/collection.rb +40 -0
  56. data/lib/puree/xml_extractor/dataset.rb +305 -0
  57. data/lib/puree/xml_extractor/download.rb +42 -0
  58. data/lib/puree/xml_extractor/event.rb +63 -0
  59. data/lib/puree/xml_extractor/journal.rb +33 -0
  60. data/lib/puree/xml_extractor/organisation.rb +75 -0
  61. data/lib/puree/xml_extractor/person.rb +57 -0
  62. data/lib/puree/xml_extractor/project.rb +135 -0
  63. data/lib/puree/xml_extractor/publication.rb +189 -0
  64. data/lib/puree/xml_extractor/publisher.rb +28 -0
  65. data/lib/puree/xml_extractor/resource.rb +71 -0
  66. data/lib/puree/xml_extractor/server.rb +32 -0
  67. data/lib/puree/xml_extractor/shared.rb +31 -0
  68. data/lib/puree/xml_extractor/xml_extractor.rb +10 -0
  69. data/puree.gemspec +11 -8
  70. data/spec/download_http_spec.rb +31 -0
  71. data/spec/open_api_dataset_http_spec.rb +15 -0
  72. data/spec/resource/collection_all_http_spec.rb +77 -0
  73. data/spec/resource/collection_http_spec.rb +65 -0
  74. data/spec/resource/dataset_http_spec.rb +104 -0
  75. data/spec/resource/event_http_spec.rb +52 -0
  76. data/spec/resource/journal_http_spec.rb +36 -0
  77. data/spec/resource/organisation_http_spec.rb +52 -0
  78. data/spec/resource/person_http_spec.rb +48 -0
  79. data/spec/resource/project_http_spec.rb +76 -0
  80. data/spec/resource/publication_http_spec.rb +78 -0
  81. data/spec/resource/publisher_http_spec.rb +26 -0
  82. data/spec/server_http_spec.rb +26 -0
  83. data/spec/spec_helper.rb +106 -21
  84. metadata +110 -46
  85. data/lib/puree/collection.rb +0 -285
  86. data/lib/puree/configuration.rb +0 -15
  87. data/lib/puree/dataset.rb +0 -483
  88. data/lib/puree/date.rb +0 -63
  89. data/lib/puree/download.rb +0 -189
  90. data/lib/puree/event.rb +0 -133
  91. data/lib/puree/journal.rb +0 -75
  92. data/lib/puree/map.rb +0 -68
  93. data/lib/puree/organisation.rb +0 -177
  94. data/lib/puree/person.rb +0 -136
  95. data/lib/puree/project.rb +0 -231
  96. data/lib/puree/publication.rb +0 -258
  97. data/lib/puree/publisher.rb +0 -64
  98. data/lib/puree/resource.rb +0 -261
  99. data/lib/puree/server.rb +0 -156
  100. data/spec/collection_spec.rb +0 -62
  101. data/spec/dataset_spec.rb +0 -148
  102. data/spec/download_spec.rb +0 -33
  103. data/spec/event_spec.rb +0 -108
  104. data/spec/journal_spec.rb +0 -92
  105. data/spec/organisation_spec.rb +0 -112
  106. data/spec/person_spec.rb +0 -104
  107. data/spec/project_spec.rb +0 -120
  108. data/spec/publication_spec.rb +0 -128
  109. data/spec/publisher_spec.rb +0 -89
  110. data/spec/server_spec.rb +0 -36
@@ -0,0 +1,42 @@
1
+ module Puree
2
+
3
+ module XMLExtractor
4
+
5
+ # Download XML extractor.
6
+ #
7
+ class Download < Puree::XMLExtractor::Base
8
+
9
+ def initialize(xml:)
10
+ @resource_type = :download
11
+ super
12
+ end
13
+
14
+ # Statistic
15
+ #
16
+ # @return [Array<Puree::Model::DownloadHeader>]
17
+ def statistics
18
+ path = "#{service_response_name}/downloadCount"
19
+ xpath_result = @doc.xpath(path)
20
+ data_arr = []
21
+ xpath_result.each { |i|
22
+ model = Puree::Model::DownloadHeader.new
23
+ model.uuid = i.attr('uuid').strip
24
+ model.count = i.attr('downloads').strip.to_i
25
+ data_arr << model
26
+ }
27
+ data_arr.uniq { |d| d.uuid }
28
+ end
29
+
30
+ # Is there any data after get?
31
+ #
32
+ # @return [Boolean]
33
+ def get_data?
34
+ # TO DO Inefficient!
35
+ statistics.size ? true : false
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,63 @@
1
+ module Puree
2
+
3
+ module XMLExtractor
4
+
5
+ # Event XML extractor.
6
+ #
7
+ class Event < Puree::XMLExtractor::Resource
8
+
9
+ def initialize(xml:)
10
+ super
11
+ @resource_type = :event
12
+ end
13
+
14
+ # @return [String, nil]
15
+ def city
16
+ xpath_query_for_single_value '/city'
17
+ end
18
+
19
+ # @return [String, nil]
20
+ def country
21
+ xpath_query_for_single_value '/country/term/localizedString'
22
+ end
23
+
24
+ # @return [Puree::Model::TemporalRange, nil]
25
+ def date
26
+ xpath_result = xpath_query '/dateRange'
27
+ range_start_str = xpath_result.xpath('startDate').text.strip
28
+ range_end_str = xpath_result.xpath('endDate').text.strip
29
+ if !range_start_str.empty?
30
+ range = Puree::Model::TemporalRange.new
31
+ range.start = Time.parse range_start_str
32
+ if !range_end_str.empty?
33
+ range.end = Time.parse range_end_str
34
+ end
35
+ range
36
+ end
37
+ end
38
+
39
+ # @return [String, nil]
40
+ def description
41
+ xpath_query_for_single_value '/description'
42
+ end
43
+
44
+ # @return [String, nil]
45
+ def location
46
+ xpath_query_for_single_value '/location'
47
+ end
48
+
49
+ # @return [String, nil]
50
+ def title
51
+ xpath_query_for_single_value '/title/localizedString'
52
+ end
53
+
54
+ # @return [String, nil]
55
+ def type
56
+ xpath_query_for_single_value '//typeClassification/term/localizedString'
57
+ end
58
+
59
+ end
60
+
61
+ end
62
+
63
+ end
@@ -0,0 +1,33 @@
1
+ module Puree
2
+
3
+ module XMLExtractor
4
+
5
+ # Journal XML extractor.
6
+ #
7
+ class Journal < Puree::XMLExtractor::Resource
8
+
9
+ def initialize(xml:)
10
+ super
11
+ @resource_type = :journal
12
+ end
13
+
14
+ # @return [String, nil]
15
+ def issn
16
+ xpath_query_for_single_value '/issns/issn/string'
17
+ end
18
+
19
+ # @return [String, nil]
20
+ def publisher
21
+ xpath_query_for_single_value '/publisher/name'
22
+ end
23
+
24
+ # @return [String, nil]
25
+ def title
26
+ xpath_query_for_single_value '/titles/title/string'
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,75 @@
1
+ module Puree
2
+
3
+ module XMLExtractor
4
+
5
+ # Organisation XML extractor.
6
+ #
7
+ class Organisation < Puree::XMLExtractor::Resource
8
+
9
+ def initialize(xml:)
10
+ super
11
+ @resource_type = :organisation
12
+ end
13
+
14
+ # @return [Array<Puree::Model::Address>]
15
+ def address
16
+ xpath_result = xpath_query '/addresses/classifiedAddress'
17
+ data = []
18
+ xpath_result.each do |d|
19
+ a = Puree::Model::Address.new
20
+ street = d.xpath('street').text.strip
21
+ a.street = street unless street.empty?
22
+ building = d.xpath('building').text.strip
23
+ a.building = building unless building.empty?
24
+ postcode = d.xpath('postalCode').text.strip
25
+ a.postcode = postcode unless building.empty?
26
+ city = d.xpath('city').text.strip
27
+ a.city = city unless city.empty?
28
+ country = d.xpath('country/term/localizedString').text.strip
29
+ a.country = country unless country.empty?
30
+ data << a
31
+ end
32
+ data.uniq { |d| d.street }
33
+ end
34
+
35
+ # @return [Array<String>]
36
+ def email_addresses
37
+ xpath_query_for_multi_value '/emails/classificationDefinedStringFieldExtension/value'
38
+ end
39
+
40
+ # @return [String, nil]
41
+ def name
42
+ xpath_query_for_single_value '/name/localizedString'
43
+ end
44
+
45
+ # @return [Array<Puree::Model::OrganisationHeader>]
46
+ def organisations
47
+ xpath_result = xpath_query '/organisations/organisation'
48
+ Puree::XMLExtractor::Shared.organisation_multi_header xpath_result
49
+ end
50
+
51
+ # @return [Puree::Model::OrganisationHeader, nil]
52
+ def parent
53
+ organisations.first unless organisations.empty?
54
+ end
55
+
56
+ # @return [Array<String>]
57
+ def phone_numbers
58
+ xpath_query_for_multi_value '/phoneNumbers/classificationDefinedStringFieldExtension/value'
59
+ end
60
+
61
+ # @return [String, nil]
62
+ def type
63
+ xpath_query_for_single_value '/typeClassification/term/localizedString'
64
+ end
65
+
66
+ # @return [Array<String>]
67
+ def urls
68
+ xpath_query_for_multi_value '/webAddresses/classificationDefinedFieldExtension/value/localizedString'
69
+ end
70
+
71
+ end
72
+
73
+ end
74
+
75
+ end
@@ -0,0 +1,57 @@
1
+ module Puree
2
+
3
+ module XMLExtractor
4
+
5
+ # Person XML extractor.
6
+ #
7
+ class Person < Puree::XMLExtractor::Resource
8
+
9
+ def initialize(xml:)
10
+ super
11
+ @resource_type = :person
12
+ end
13
+
14
+ # @return [Array<Puree::Model::OrganisationHeader>]
15
+ def affiliations
16
+ xpath_result = xpath_query '//organisation'
17
+ Puree::XMLExtractor::Shared.organisation_multi_header xpath_result
18
+ end
19
+
20
+ # @return [Array<String>]
21
+ def email_addresses
22
+ xpath_query_for_multi_value '//emails/classificationDefinedStringFieldExtension/value'
23
+ end
24
+
25
+ # @return [Array<String>]
26
+ def image_urls
27
+ xpath_query_for_multi_value '/photos/file/url'
28
+ end
29
+
30
+ # @return [Array<String>]
31
+ def keywords
32
+ xpath_query_for_multi_value '//keywordGroup/keyword/userDefinedKeyword/freeKeyword'
33
+ end
34
+
35
+ # @return [Puree::Model::PersonName, nil]
36
+ def name
37
+ xpath_result = xpath_query '/name'
38
+ if xpath_result
39
+ first = xpath_result.xpath('firstName').text.strip
40
+ last = xpath_result.xpath('lastName').text.strip
41
+ model = Puree::Model::PersonName.new
42
+ model.first = first unless first.empty?
43
+ model.last = last unless last.empty?
44
+ model
45
+ end
46
+ end
47
+
48
+ # @return [String, nil]
49
+ def orcid
50
+ xpath_query_for_single_value '/orcid'
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,135 @@
1
+ module Puree
2
+
3
+ module XMLExtractor
4
+
5
+ # Project XML extractor.
6
+ #
7
+ class Project < Puree::XMLExtractor::Resource
8
+
9
+ def initialize(xml:)
10
+ super
11
+ @resource_type = :project
12
+ end
13
+
14
+ # @return [String, nil]
15
+ def acronym
16
+ xpath_query_for_single_value '/acronym'
17
+ end
18
+
19
+ # @return [String, nil]
20
+ def description
21
+ xpath_query_for_single_value '/description/localizedString'
22
+ end
23
+
24
+ # @return [Array<Puree::Model::OrganisationHeader>]
25
+ def organisations
26
+ xpath_result = xpath_query '/organisations/association/organisation'
27
+ Puree::XMLExtractor::Shared.organisation_multi_header xpath_result
28
+ end
29
+
30
+ # @return [Puree::Model::OrganisationHeader, nil]
31
+ def owner
32
+ xpath_result = xpath_query '/owner'
33
+ Puree::XMLExtractor::Shared.organisation_header xpath_result
34
+ end
35
+
36
+ # @return [Array<Puree::Model::EndeavourPerson>]
37
+ def persons_internal
38
+ persons 'internal'
39
+ end
40
+
41
+ # @return [Array<Puree::Model::EndeavourPerson>]
42
+ def persons_external
43
+ persons 'external'
44
+ end
45
+
46
+ # @return [Array<Puree::Model::EndeavourPerson>]
47
+ def persons_other
48
+ persons 'other'
49
+ end
50
+
51
+ # @return [String, nil]
52
+ def status
53
+ xpath_query_for_single_value '/status/term/localizedString'
54
+ end
55
+
56
+ # @return [Puree::Model::TemporalRange, nil]
57
+ def temporal_expected
58
+ temporal_range '/expectedStartDate', '/expectedEndDate'
59
+ end
60
+
61
+ # @return [Puree::Model::TemporalRange, nil]
62
+ def temporal_actual
63
+ temporal_range '/startFinishDate/startDate', '/startFinishDate/endDate'
64
+ end
65
+
66
+ # @return [String, nil]
67
+ def title
68
+ xpath_query_for_single_value '/title/localizedString'
69
+ end
70
+
71
+ # @return [String, nil]
72
+ def type
73
+ xpath_query_for_single_value '/typeClassification/term/localizedString'
74
+ end
75
+
76
+ # @return [String, nil]
77
+ def url
78
+ xpath_query_for_single_value '/projectURL'
79
+ end
80
+
81
+ private
82
+
83
+ # @return [Array<Endeavour::Person>]
84
+ def persons(type)
85
+ xpath_result = xpath_query '/persons/participantAssociation'
86
+ arr = []
87
+ xpath_result.each do |i|
88
+ uuid_internal = i.at_xpath('person/@uuid')
89
+ uuid_external = i.at_xpath('externalPerson/@uuid')
90
+ if uuid_internal
91
+ person_type = 'internal'
92
+ uuid = uuid_internal.text.strip
93
+ elsif uuid_external
94
+ person_type = 'external'
95
+ uuid = uuid_external.text.strip
96
+ else
97
+ person_type = 'other'
98
+ uuid = ''
99
+ end
100
+ if person_type === type
101
+ person = Puree::Model::EndeavourPerson.new
102
+ person.uuid = uuid
103
+
104
+ name = Puree::Model::PersonName.new
105
+ name.first = i.xpath('person/name/firstName').text.strip
106
+ name.last = i.xpath('person/name/lastName').text.strip
107
+ person.name = name
108
+
109
+ role = i.xpath('personRole/term/localizedString').text.strip
110
+ person.role = role
111
+
112
+ arr << person if person.data?
113
+ end
114
+ end
115
+ arr.uniq { |d| d.uuid }
116
+ end
117
+
118
+ # @return [Puree::Model::TemporalRange, nil]
119
+ def temporal_range(start_path, end_path)
120
+ range_start = xpath_query_for_single_value start_path
121
+ range_end = xpath_query_for_single_value end_path
122
+ if range_start || range_end
123
+ range = Puree::Model::TemporalRange.new
124
+ range.start = Time.new range_start if range_start
125
+ range.end = Time.new range_end if range_end
126
+ return range
127
+ end
128
+ nil
129
+ end
130
+
131
+ end
132
+
133
+ end
134
+
135
+ end
@@ -0,0 +1,189 @@
1
+ module Puree
2
+
3
+ module XMLExtractor
4
+
5
+ # Publication XMLextractor.
6
+ #
7
+ class Publication < Puree::XMLExtractor::Resource
8
+
9
+ def initialize(xml:)
10
+ @resource_type = :publication
11
+ super
12
+ end
13
+
14
+ # @return [String, nil]
15
+ def category
16
+ xpath_query_for_single_value '/publicationCategory/publicationCategory/term/localizedString'
17
+ end
18
+
19
+ # @return [String, nil]
20
+ def description
21
+ xpath_query_for_single_value '/abstract/localizedString'
22
+ end
23
+
24
+ # @return [String, nil]
25
+ def doi
26
+ xpath_query_for_single_value '//doi'
27
+ end
28
+
29
+ # @return [Puree::Model::EventHeader, nil]
30
+ def event
31
+ xpath_result = xpath_query '/event'
32
+ if !xpath_result.empty?
33
+ header = Puree::Model::EventHeader.new
34
+ header.uuid = xpath_result.xpath('@uuid').text.strip
35
+ header.title = xpath_result.xpath('title/localizedString').text.strip
36
+ return header if header.data?
37
+ end
38
+ nil
39
+ end
40
+
41
+ # @return [Array<Puree::Model::File>]
42
+ def files
43
+ xpath_result = xpath_query '/electronicVersionAssociations/electronicVersionFileAssociations/electronicVersionFileAssociation/file'
44
+ docs = []
45
+ xpath_result.each do |d|
46
+ model = Puree::Model::File.new
47
+ model.name = d.xpath('fileName').text.strip
48
+ model.mime = d.xpath('mimeType').text.strip
49
+ model.size = d.xpath('size').text.strip.to_i
50
+ model.url = d.xpath('url').text.strip
51
+ docs << model
52
+ end
53
+ docs.uniq { |d| d.url }
54
+ end
55
+
56
+ # @return [Array<Puree::Model::OrganisationHeader>]
57
+ def organisations
58
+ xpath_result = xpath_query '/organisations/association/organisation'
59
+ Puree::XMLExtractor::Shared.organisation_multi_header xpath_result
60
+ end
61
+
62
+ # @return [Fixnum, nil]
63
+ def pages
64
+ xpath_query_for_single_value('/numberOfPages').to_i
65
+ end
66
+
67
+ # @return [Array<Puree::Model::EndeavourPerson>]
68
+ def persons_internal
69
+ persons 'internal'
70
+ end
71
+
72
+ # @return [Array<Puree::Model::EndeavourPerson>]
73
+ def persons_external
74
+ persons 'external'
75
+ end
76
+
77
+ # @return [Array<Puree::Model::EndeavourPerson>]
78
+ def persons_other
79
+ persons 'other'
80
+ end
81
+
82
+ # @return [Array<Puree::Model::PublicationStatus>]
83
+ def statuses
84
+ xpath_result = xpath_query '/publicationStatuses/publicationStatus'
85
+ data = []
86
+ xpath_result.each do |i|
87
+ s = Puree::Model::PublicationStatus.new
88
+ s.stage = i.xpath('publicationStatus/term/localizedString').text.strip
89
+
90
+ ymd = {}
91
+ ymd['year'] = i.xpath('publicationDate/year').text.strip
92
+ ymd['month'] = i.xpath('publicationDate/month').text.strip
93
+ ymd['day'] = i.xpath('publicationDate/day').text.strip
94
+
95
+ s.date = Puree::Util::Date.hash_to_time ymd
96
+
97
+ data << s
98
+ end
99
+ data.uniq { |d| d.stage }
100
+ end
101
+
102
+ # @return [String, nil]
103
+ def subtitle
104
+ xpath_query_for_single_value '/subtitle'
105
+ end
106
+
107
+ # @return [String, nil]
108
+ def title
109
+ xpath_query_for_single_value '/title'
110
+ end
111
+
112
+ # @return [String, nil]
113
+ def type
114
+ xpath_query_for_single_value '/typeClassification/term/localizedString'
115
+ end
116
+
117
+ private
118
+
119
+ # @return [Array<Endeavour::Person>]
120
+ def persons(type)
121
+ xpath_result = xpath_query '/persons/personAssociation'
122
+ arr = []
123
+ xpath_result.each do |i|
124
+ uuid_internal = i.at_xpath('person/@uuid')
125
+ uuid_external = i.at_xpath('externalPerson/@uuid')
126
+ if uuid_internal
127
+ person_type = 'internal'
128
+ uuid = uuid_internal.text.strip
129
+ elsif uuid_external
130
+ person_type = 'external'
131
+ uuid = uuid_external.text.strip
132
+ else
133
+ person_type = 'other'
134
+ uuid = ''
135
+ end
136
+ if person_type === type
137
+ person = Puree::Model::EndeavourPerson.new
138
+ person.uuid = uuid
139
+
140
+ name = Puree::Model::PersonName.new
141
+ name.first = i.xpath('name/firstName').text.strip
142
+ name.last = i.xpath('name/lastName').text.strip
143
+ person.name = name
144
+
145
+ role_uri = i.xpath('personRole/uri').text.strip
146
+ person.role = roles[role_uri]
147
+
148
+ arr << person if person.data?
149
+ end
150
+ end
151
+ arr.uniq { |d| d.uuid }
152
+ end
153
+
154
+ def roles
155
+ {
156
+ # Should build using '/dk/atira/pure/researchoutput/roles/' as prefix, with parameter
157
+
158
+ ## Article
159
+ '/dk/atira/pure/researchoutput/roles/contributiontojournal/author' => 'Author',
160
+ '/dk/atira/pure/researchoutput/roles/contributiontojournal/illustrator' => 'Illustrator',
161
+ '/dk/atira/pure/researchoutput/roles/contributiontojournal/editor' => 'Editor',
162
+ '/dk/atira/pure/researchoutput/roles/contributiontojournal/translator' => 'Translator',
163
+ '/dk/atira/pure/researchoutput/roles/contributiontojournal/publisher' => 'Publisher',
164
+ '/dk/atira/pure/researchoutput/roles/contributiontojournal/guesteditor' => 'Guest Editor',
165
+
166
+ ## Chapter
167
+ # Author
168
+ # Illustrator
169
+ # Editor
170
+ # Translator
171
+ # Publisher
172
+
173
+ # ... many, many more research output types ...
174
+
175
+ # Examples of others
176
+ '/dk/atira/pure/researchoutput/roles/bookanthology/author' => 'Author',
177
+ '/dk/atira/pure/researchoutput/roles/othercontribution/author' => 'Author',
178
+ '/dk/atira/pure/researchoutput/roles/thesis/author' => 'Author',
179
+ '/dk/atira/pure/researchoutput/roles/workingpaper/author' => 'Author',
180
+ '/dk/atira/pure/researchoutput/roles/internalexternal/thesis/supervisor' => 'Supervisor',
181
+ '/dk/atira/pure/researchoutput/roles/nontextual/artist' => 'Artist'
182
+ }
183
+ end
184
+
185
+ end
186
+
187
+ end
188
+
189
+ end