rkd 0.1.0 → 0.2.0
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 +4 -4
- data/.gitignore +1 -0
- data/.gitlab-ci.yml +37 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile +0 -2
- data/Gemfile.lock +74 -0
- data/README.md +33 -7
- data/Rakefile +1 -1
- data/docs/first query.sparql +38 -0
- data/docs/fourth_query.sparql +63 -0
- data/docs/second_query.sparql +22 -0
- data/docs/third_query.sparql +53 -0
- data/lib/r_k_d/artist.rb +252 -0
- data/lib/r_k_d/config.rb +27 -0
- data/lib/r_k_d/date_span.rb +42 -0
- data/lib/r_k_d/helpers/date_parsing.rb +17 -0
- data/lib/r_k_d/imprecise_date.rb +47 -0
- data/lib/r_k_d/institution.rb +28 -0
- data/lib/r_k_d/performance.rb +32 -0
- data/lib/r_k_d/place.rb +38 -0
- data/lib/r_k_d/query/elastic_search.rb +64 -0
- data/lib/r_k_d/query/file_cache.rb +40 -0
- data/lib/r_k_d/query/http.rb +24 -0
- data/lib/r_k_d/query/sparql.rb +77 -0
- data/lib/r_k_d/type.rb +11 -0
- data/lib/r_k_d/version.rb +3 -0
- data/lib/r_k_d.rb +24 -0
- data/lib/rkd.rb +1 -6
- data/rkd.gemspec +16 -14
- metadata +63 -13
- data/lib/rkd/version.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 90fda4ea793f4c4ae3fb171d56b8919728b3e9f8a71d6b9ca636ee22ab6d648f
|
4
|
+
data.tar.gz: 0633b70cf3ba381369e6b1ec4c56d9540b545c965c847edb764bfad40e00d507
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 405e9a82dd92ffb06e1ee1144634e3dd41d7ec0044d6f9a76ad6ba29f90fab57acb2da49e73415680e2b784b0e95756b2505c56bc85a1980d9621013dfa46a06
|
7
|
+
data.tar.gz: 467289a5a7b19934bdb5f0ca48c4a56075c8ffd9b32783e327015907b04ed92701f5184f8da94d96460cf80c3d0fb76dda765c4d59a822118b514e26d038b0e4
|
data/.gitignore
CHANGED
data/.gitlab-ci.yml
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# This file is a template, and might need editing before it works on your project.
|
2
|
+
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
|
3
|
+
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
|
4
|
+
#
|
5
|
+
# To contribute improvements to CI/CD templates, please follow the Development guide at:
|
6
|
+
# https://docs.gitlab.com/ee/development/cicd/templates.html
|
7
|
+
# This specific template is located at:
|
8
|
+
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
|
9
|
+
|
10
|
+
# Official language image. Look for the different tagged releases at:
|
11
|
+
# https://hub.docker.com/r/library/ruby/tags/
|
12
|
+
image: ruby:latest
|
13
|
+
|
14
|
+
|
15
|
+
# Cache gems in between builds
|
16
|
+
cache:
|
17
|
+
paths:
|
18
|
+
- vendor/ruby
|
19
|
+
|
20
|
+
# This is a basic example for a gem or script which doesn't use
|
21
|
+
# services such as redis or postgres
|
22
|
+
before_script:
|
23
|
+
- ruby -v # Print out ruby version for debugging
|
24
|
+
# Uncomment next line if your rails app needs a JS runtime:
|
25
|
+
# - apt-get update -q && apt-get install nodejs -yqq
|
26
|
+
- bundle config set --local deployment true # Install dependencies into ./vendor/ruby
|
27
|
+
- bundle install -j $(nproc)
|
28
|
+
- gem install simplecov
|
29
|
+
|
30
|
+
standardrb:
|
31
|
+
script:
|
32
|
+
- bundle exec standardrb
|
33
|
+
|
34
|
+
|
35
|
+
test:
|
36
|
+
script:
|
37
|
+
- rake
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.3.4
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# 0.3.0 (in progress)
|
2
|
+
|
3
|
+
* RKD SPARQL API implemented
|
4
|
+
* Artist.find
|
5
|
+
* Artist#public_url (returning a human readable page on the RKD website)
|
6
|
+
* few Rails conveniences (that shouldn't hurt non-Rails solution)
|
7
|
+
* Artist#to_partial_path
|
8
|
+
* Institution
|
9
|
+
* Handling network errors
|
10
|
+
|
11
|
+
# 0.2.0
|
12
|
+
|
13
|
+
* RKD Search API implemented
|
14
|
+
|
15
|
+
# 0.1.0 Init
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
rkd (0.2.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ast (2.4.2)
|
10
|
+
docile (1.4.1)
|
11
|
+
json (2.7.2)
|
12
|
+
language_server-protocol (3.17.0.3)
|
13
|
+
lint_roller (1.1.0)
|
14
|
+
minitest (5.25.1)
|
15
|
+
parallel (1.26.3)
|
16
|
+
parser (3.3.5.0)
|
17
|
+
ast (~> 2.4.1)
|
18
|
+
racc
|
19
|
+
racc (1.8.1)
|
20
|
+
rainbow (3.1.1)
|
21
|
+
rake (10.5.0)
|
22
|
+
regexp_parser (2.9.2)
|
23
|
+
rexml (3.3.7)
|
24
|
+
rubocop (1.65.1)
|
25
|
+
json (~> 2.3)
|
26
|
+
language_server-protocol (>= 3.17.0)
|
27
|
+
parallel (~> 1.10)
|
28
|
+
parser (>= 3.3.0.2)
|
29
|
+
rainbow (>= 2.2.2, < 4.0)
|
30
|
+
regexp_parser (>= 2.4, < 3.0)
|
31
|
+
rexml (>= 3.2.5, < 4.0)
|
32
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
33
|
+
ruby-progressbar (~> 1.7)
|
34
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
35
|
+
rubocop-ast (1.32.3)
|
36
|
+
parser (>= 3.3.1.0)
|
37
|
+
rubocop-performance (1.21.1)
|
38
|
+
rubocop (>= 1.48.1, < 2.0)
|
39
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
40
|
+
ruby-progressbar (1.13.0)
|
41
|
+
simplecov (0.22.0)
|
42
|
+
docile (~> 1.1)
|
43
|
+
simplecov-html (~> 0.11)
|
44
|
+
simplecov_json_formatter (~> 0.1)
|
45
|
+
simplecov-html (0.13.1)
|
46
|
+
simplecov_json_formatter (0.1.4)
|
47
|
+
standard (1.40.0)
|
48
|
+
language_server-protocol (~> 3.17.0.2)
|
49
|
+
lint_roller (~> 1.0)
|
50
|
+
rubocop (~> 1.65.0)
|
51
|
+
standard-custom (~> 1.0.0)
|
52
|
+
standard-performance (~> 1.4)
|
53
|
+
standard-custom (1.0.2)
|
54
|
+
lint_roller (~> 1.0)
|
55
|
+
rubocop (~> 1.50)
|
56
|
+
standard-performance (1.4.0)
|
57
|
+
lint_roller (~> 1.1)
|
58
|
+
rubocop-performance (~> 1.21.0)
|
59
|
+
unicode-display_width (2.6.0)
|
60
|
+
|
61
|
+
PLATFORMS
|
62
|
+
arm64-darwin-23
|
63
|
+
ruby
|
64
|
+
|
65
|
+
DEPENDENCIES
|
66
|
+
bundler (> 1)
|
67
|
+
minitest (~> 5.0)
|
68
|
+
rake (~> 10.0)
|
69
|
+
rkd!
|
70
|
+
simplecov (~> 0.22)
|
71
|
+
standard (~> 1)
|
72
|
+
|
73
|
+
BUNDLED WITH
|
74
|
+
2.5.18
|
data/README.md
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# RKD (unofficial)
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
3
|
+
This is the RKD gem. A gem that helps ruby-developers to interact with the vast collection of data from the RKD in a ruby-friendly manner.
|
6
4
|
|
7
5
|
## Installation
|
8
6
|
|
@@ -22,7 +20,35 @@ Or install it yourself as:
|
|
22
20
|
|
23
21
|
## Usage
|
24
22
|
|
25
|
-
|
23
|
+
### Searching for an artist:
|
24
|
+
|
25
|
+
```
|
26
|
+
artists = RKD::Artist.search("Rembrandt") # returns array of results
|
27
|
+
artist = artists.first # best hit :)
|
28
|
+
artist.enrich! # enrich the data from the sparql endpoints
|
29
|
+
```
|
30
|
+
|
31
|
+
### Just getting a single artist
|
32
|
+
|
33
|
+
```
|
34
|
+
RKD::Artist.find(123)
|
35
|
+
```
|
36
|
+
|
37
|
+
### Retrieving data
|
38
|
+
|
39
|
+
Just browse the methods:
|
40
|
+
|
41
|
+
```
|
42
|
+
artist.birth_place.geoname_id
|
43
|
+
artist.performances.work.first.place.lat, artist.performances.work.first.place.lon
|
44
|
+
artist.performances.work.first.place.geoname_id
|
45
|
+
artist.performances.work.first.date_span.begin # returns a RKD::ImpreciseDate or Date
|
46
|
+
artist.performances.study.map{|s| s.label}
|
47
|
+
artist.types # []
|
48
|
+
artist.name_variants
|
49
|
+
```
|
50
|
+
|
51
|
+
It is all powered by a combination of a ElasticSearch and SPARQL API call, but now without the hassle of making these queries manually.
|
26
52
|
|
27
53
|
## Development
|
28
54
|
|
@@ -32,7 +58,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
32
58
|
|
33
59
|
## Contributing
|
34
60
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://
|
61
|
+
Bug reports and pull requests are welcome on GitHub at https://gitlab.com/murb/rkd/. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
36
62
|
|
37
63
|
## License
|
38
64
|
|
@@ -40,4 +66,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
40
66
|
|
41
67
|
## Code of Conduct
|
42
68
|
|
43
|
-
Everyone interacting in the Rkd project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://
|
69
|
+
Everyone interacting in the Rkd project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://gitlab.com/murb/rkd/-/blob/main/CODE_OF_CONDUCT.md).
|
data/Rakefile
CHANGED
@@ -0,0 +1,38 @@
|
|
1
|
+
PREFIX rkd: <https://data.rkd.nl/def#>
|
2
|
+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
3
|
+
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
|
4
|
+
PREFIX crm: <http://www.cidoc-crm.org/cidoc-crm/>
|
5
|
+
prefix la: <https://linked.art/ns/terms/>
|
6
|
+
|
7
|
+
SELECT ?property ?propertyLabel ?value ?symbolicContent ?prefLabel ?tookPlaceAt ?placePoint ?placeLabel ?placeGeoname ?timeSpan ?start ?end
|
8
|
+
WHERE {
|
9
|
+
<https://data.rkd.nl/artists/66219> ?property ?value.
|
10
|
+
FILTER (
|
11
|
+
!(?property in (crm:P67i_is_referred_to_by, crm:P1_is_identified_by, crm:P62i_is_depicted_by, la:member_of))
|
12
|
+
)
|
13
|
+
OPTIONAL {
|
14
|
+
?property rdfs:label ?propertyLabel.
|
15
|
+
FILTER (lang(?propertyLabel) = "en")
|
16
|
+
}
|
17
|
+
OPTIONAL {
|
18
|
+
?value crm:P190_has_symbolic_content ?symbolicContent
|
19
|
+
}
|
20
|
+
OPTIONAL {
|
21
|
+
?value skos:prefLabel ?prefLabel
|
22
|
+
FILTER (lang(?prefLabel) = "en")
|
23
|
+
}
|
24
|
+
OPTIONAL {
|
25
|
+
?value crm:P7_took_place_at ?tookPlaceAt.
|
26
|
+
?value crm:P4_has_time-span ?timeSpan.
|
27
|
+
?tookPlaceAt crm:P168_place_is_defined_by ?placePoint.
|
28
|
+
?tookPlaceAt rdfs:label ?placeLabel.
|
29
|
+
?tookPlaceAt skos:exactMatch ?placeGeoname.
|
30
|
+
?timeSpan crm:P82a_begin_of_the_begin ?start.
|
31
|
+
?timeSpan crm:P82b_end_of_the_end ?end.
|
32
|
+
|
33
|
+
FILTER
|
34
|
+
(?property in (crm:P100i_died_in, crm:P98i_was_born))
|
35
|
+
}
|
36
|
+
|
37
|
+
|
38
|
+
}
|
@@ -0,0 +1,63 @@
|
|
1
|
+
PREFIX rkd: <https://data.rkd.nl/def#>
|
2
|
+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
3
|
+
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
|
4
|
+
PREFIX crm: <http://www.cidoc-crm.org/cidoc-crm/>
|
5
|
+
prefix la: <https://linked.art/ns/terms/>
|
6
|
+
|
7
|
+
SELECT ?property ?propertyLabel ?value ?symbolicContent ?prefLabel ?tookPlaceAt ?tookPlaceAtTimeSpan ?tookPlaceAtTimeSpanBegin ?tookPlaceAtTimeSpanEnd ?placePoint ?placeLabel ?placeGeoname ?timeSpan ?start ?end ?domain ?range ?studyLabel
|
8
|
+
WHERE {
|
9
|
+
<https://data.rkd.nl/artists/32439> ?property ?value.
|
10
|
+
FILTER (
|
11
|
+
!(?property in (crm:P67i_is_referred_to_by, crm:P1_is_identified_by, crm:P62i_is_depicted_by, la:member_of))
|
12
|
+
)
|
13
|
+
OPTIONAL {
|
14
|
+
?property rdfs:label ?propertyLabel.
|
15
|
+
FILTER (lang(?propertyLabel) = "en")
|
16
|
+
}
|
17
|
+
OPTIONAL {
|
18
|
+
?value crm:P190_has_symbolic_content ?symbolicContent
|
19
|
+
}
|
20
|
+
OPTIONAL {
|
21
|
+
?value skos:prefLabel ?prefLabel
|
22
|
+
FILTER (lang(?prefLabel) = "en")
|
23
|
+
}
|
24
|
+
OPTIONAL {
|
25
|
+
?value crm:P7_took_place_at ?tookPlaceAt.
|
26
|
+
?value crm:P4_has_time-span ?timeSpan.
|
27
|
+
?tookPlaceAt crm:P168_place_is_defined_by ?placePoint.
|
28
|
+
?tookPlaceAt rdfs:label ?placeLabel.
|
29
|
+
?tookPlaceAt skos:exactMatch ?placeGeoname.
|
30
|
+
?timeSpan crm:P82a_begin_of_the_begin ?start.
|
31
|
+
?timeSpan crm:P82b_end_of_the_end ?end.
|
32
|
+
# FILTER
|
33
|
+
# (
|
34
|
+
# #?property in (crm:P100i_died_in, crm:P98i_was_born, crm:P14i_performed)
|
35
|
+
# # &&
|
36
|
+
# # STRSTARTS(STR(?placeGeoname), "https://sws.geonames.org/")
|
37
|
+
# )
|
38
|
+
}
|
39
|
+
OPTIONAL {
|
40
|
+
?value crm:P7_took_place_at ?tookPlaceAt.
|
41
|
+
?tookPlaceAt rdfs:label ?placeLabel.
|
42
|
+
?tookPlaceAt skos:exactMatch ?placeGeoname.
|
43
|
+
|
44
|
+
|
45
|
+
FILTER
|
46
|
+
(
|
47
|
+
?property in (crm:P100i_died_in, crm:P98i_was_born, crm:P14i_performed)
|
48
|
+
&&
|
49
|
+
STRSTARTS(STR(?placeGeoname), "https://sws.geonames.org/")
|
50
|
+
)
|
51
|
+
}
|
52
|
+
OPTIONAL {
|
53
|
+
?value crm:P01i_is_domain_of ?domain.
|
54
|
+
?domain crm:P02_has_range ?range.
|
55
|
+
?range skos:prefLabel ?studyLabel.
|
56
|
+
}
|
57
|
+
OPTIONAL {
|
58
|
+
?value crm:P4_has_time-span ?tookPlaceAtTimeSpan.
|
59
|
+
?tookPlaceAtTimeSpan crm:P82a_begin_of_the_begin ?tookPlaceAtTimeSpanBegin.
|
60
|
+
?tookPlaceAtTimeSpan crm:P82b_end_of_the_end ?tookPlaceAtTimeSpanEnd.
|
61
|
+
|
62
|
+
}
|
63
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
PREFIX rkd: <https://data.rkd.nl/def#>
|
2
|
+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
3
|
+
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
|
4
|
+
PREFIX crm: <http://www.cidoc-crm.org/cidoc-crm/>
|
5
|
+
prefix la: <https://linked.art/ns/terms/>
|
6
|
+
prefix schema: <https://schema.org/>
|
7
|
+
prefix thesaurus: <https://data.rkd.nl/thesaurus/>
|
8
|
+
|
9
|
+
SELECT DISTINCT ?property ?value ?workLocation ?placeGeoname ?somethingElse
|
10
|
+
WHERE {
|
11
|
+
<https://data.rkd.nl/artists/66219> ?property ?value
|
12
|
+
OPTIONAL {
|
13
|
+
?value schema:workLocation ?workLocation .
|
14
|
+
FILTER(STRSTARTS(STR(?workLocation), "https://data.rkd.nl/thesaurus"))
|
15
|
+
}
|
16
|
+
OPTIONAL {
|
17
|
+
SERVICE <https://api.rkd.triply.cc/datasets/rkd/RKD-Knowledge-Graph/sparql> {
|
18
|
+
?workLocation a skos:Concept .
|
19
|
+
?workLocation skos:exactMatch ?placeGeoname
|
20
|
+
}
|
21
|
+
}
|
22
|
+
}
|
@@ -0,0 +1,53 @@
|
|
1
|
+
PREFIX rkd: <https://data.rkd.nl/def#>
|
2
|
+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
3
|
+
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
|
4
|
+
PREFIX crm: <http://www.cidoc-crm.org/cidoc-crm/>
|
5
|
+
prefix la: <https://linked.art/ns/terms/>
|
6
|
+
|
7
|
+
SELECT ?property ?propertyLabel ?value ?symbolicContent ?prefLabel ?tookPlaceAt ?placePoint ?placeLabel ?placeGeoname ?timeSpan ?start ?end
|
8
|
+
WHERE {
|
9
|
+
<https://data.rkd.nl/artists/473628> ?property ?value.
|
10
|
+
FILTER (
|
11
|
+
!(?property in (crm:P67i_is_referred_to_by, crm:P1_is_identified_by, crm:P62i_is_depicted_by, la:member_of))
|
12
|
+
)
|
13
|
+
OPTIONAL {
|
14
|
+
?property rdfs:label ?propertyLabel.
|
15
|
+
FILTER (lang(?propertyLabel) = "en")
|
16
|
+
}
|
17
|
+
OPTIONAL {
|
18
|
+
?value crm:P190_has_symbolic_content ?symbolicContent
|
19
|
+
}
|
20
|
+
OPTIONAL {
|
21
|
+
?value skos:prefLabel ?prefLabel
|
22
|
+
FILTER (lang(?prefLabel) = "en")
|
23
|
+
}
|
24
|
+
OPTIONAL {
|
25
|
+
?value crm:P7_took_place_at ?tookPlaceAt.
|
26
|
+
?value crm:P4_has_time-span ?timeSpan.
|
27
|
+
?tookPlaceAt crm:P168_place_is_defined_by ?placePoint.
|
28
|
+
?tookPlaceAt rdfs:label ?placeLabel.
|
29
|
+
?tookPlaceAt skos:exactMatch ?placeGeoname.
|
30
|
+
?timeSpan crm:P82a_begin_of_the_begin ?start.
|
31
|
+
?timeSpan crm:P82b_end_of_the_end ?end.
|
32
|
+
|
33
|
+
FILTER
|
34
|
+
(
|
35
|
+
?property in (crm:P100i_died_in, crm:P98i_was_born, crm:P14i_performed)
|
36
|
+
# &&
|
37
|
+
# STRSTARTS(STR(?placeGeoname), "https://sws.geonames.org/")
|
38
|
+
)
|
39
|
+
}
|
40
|
+
OPTIONAL {
|
41
|
+
?value crm:P7_took_place_at ?tookPlaceAt.
|
42
|
+
?tookPlaceAt rdfs:label ?placeLabel.
|
43
|
+
?tookPlaceAt skos:exactMatch ?placeGeoname.
|
44
|
+
|
45
|
+
|
46
|
+
FILTER
|
47
|
+
(
|
48
|
+
?property in (crm:P100i_died_in, crm:P98i_was_born, crm:P14i_performed)
|
49
|
+
&&
|
50
|
+
STRSTARTS(STR(?placeGeoname), "https://sws.geonames.org/")
|
51
|
+
)
|
52
|
+
}
|
53
|
+
}
|
data/lib/r_k_d/artist.rb
ADDED
@@ -0,0 +1,252 @@
|
|
1
|
+
module RKD
|
2
|
+
class Artist
|
3
|
+
class NotFoundError < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
include ::RKD::Helpers::DateParsing
|
7
|
+
|
8
|
+
# @!attribute [r] id
|
9
|
+
# @return [String] the full identifier of the artist; typically the uri
|
10
|
+
# @!attribute [r] name
|
11
|
+
# @return [String] the name of the artist
|
12
|
+
# @!attribute [r] identifier
|
13
|
+
# @return [Integer] RKDid (basically the last part of the URI; which used to be the RKD Artist ID)
|
14
|
+
# @!attribute [r] gender
|
15
|
+
# @return [String] currently just returns binary forms; 'male' | 'female'
|
16
|
+
# @!attribute [r] birth_date
|
17
|
+
# @return [Date,RKD::ImpreciseDate] will return date when known, otherwise imprecise date
|
18
|
+
# @!attribute [r] death_date
|
19
|
+
# @return [Date,RKD::ImpreciseDate] will return date when known, otherwise imprecise date
|
20
|
+
# @!attribute [r] types
|
21
|
+
# @return [Array<RKD::Type>] the types associated with the artist
|
22
|
+
# @!attribute [r] updated_at
|
23
|
+
# @return [DateTime] the timestamp when the artist information was last updated
|
24
|
+
# @!attribute [r] birth_place
|
25
|
+
# @return [RKD::Place] the place where the artist was born
|
26
|
+
# @!attribute [r] death_place
|
27
|
+
# @return [RKD::Place] the place where the artist died
|
28
|
+
# @!attribute [r] name_variants
|
29
|
+
# @return [Array<String>] the different name variants of the artist
|
30
|
+
attr_reader :id, :name, :identifier, :gender, :birth_date, :death_date, :types, :updated_at, :birth_place, :death_place, :name_variants
|
31
|
+
|
32
|
+
class << self
|
33
|
+
# Searches for artists by name.
|
34
|
+
# @param name [String] the name of the artist to search for.
|
35
|
+
# @return [Array<RKD::Artist>] an array of artist objects matching the search criteria.
|
36
|
+
def search(name)
|
37
|
+
name = name.to_s.strip
|
38
|
+
|
39
|
+
return [] if name.empty?
|
40
|
+
|
41
|
+
Query::ElasticSearch.search(name, dataset: "artists").map do |artist|
|
42
|
+
new_from_search_result(artist)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Finds an artist by identifier.
|
47
|
+
# @param identifier [Integer, String] the identifier of the artist to find. It will accept both artist's RKD URI as well as RKD Artist's numeric identifiers.
|
48
|
+
# @raise [NotFoundError] if no artist is found with the given identifier.
|
49
|
+
# @return [RKD::Artist] the artist object corresponding to the given identifier.
|
50
|
+
def find(identifier)
|
51
|
+
identifier = identifier.sub("https://data.rkd.nl/artists/", "") if identifier.is_a? String
|
52
|
+
raise NotFoundError.new("No artist with id #{identifier}") if identifier.to_i == 0
|
53
|
+
identifier = identifier.to_i
|
54
|
+
|
55
|
+
found_data = Query::ElasticSearch.find(identifier, dataset: "artists")
|
56
|
+
raise NotFoundError.new("No artist found with id #{identifier}") if found_data.nil?
|
57
|
+
artist = new_from_search_result(found_data)
|
58
|
+
artist.enrich!
|
59
|
+
artist
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
# Creates a new artist object from the search result.
|
65
|
+
# @param result [Hash] the search result data.
|
66
|
+
# @return [RKD::Artist] a new artist object populated with the search result data.
|
67
|
+
def new_from_search_result(result)
|
68
|
+
RKD::Artist.new(
|
69
|
+
id: result["@id"],
|
70
|
+
identifier: result["https://data rkd nl/search#identifier"].first.to_i,
|
71
|
+
name: result["https://data rkd nl/search#kunstenaarsnaam"]&.first || result["https://data rkd nl/search#creatorName"]&.first,
|
72
|
+
gender: result["https://data rkd nl/search#geslacht"]&.join(", "),
|
73
|
+
birth_date: [result["https://data rkd nl/search#geboortedatum_begin"]&.first, result["https://data rkd nl/search#geboortedatum_eind"]&.first].compact.max_by(&:length),
|
74
|
+
birth_place_desc: result["https://data rkd nl/search#geboorteplaats"]&.first,
|
75
|
+
death_date: [result["https://data rkd nl/search#sterfdatum_begin"]&.first, result["https://data rkd nl/search#sterfdatum_eind"]&.first].compact.max_by(&:length),
|
76
|
+
death_place_desc: result["https://data rkd nl/search#sterfplaats"]&.first,
|
77
|
+
name_variants: result["https://data rkd nl/search#spellingsvariant"] || []
|
78
|
+
)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def initialize(id: nil, name: nil, identifier: nil, gender: nil, birth_date: nil, death_date: nil, birth_place_desc: nil, death_place_desc: nil, name_variants: [])
|
83
|
+
@id = id
|
84
|
+
@name = name
|
85
|
+
@identifier = identifier
|
86
|
+
@gender = gender
|
87
|
+
self.birth_date = birth_date
|
88
|
+
self.death_date = death_date
|
89
|
+
@birth_place_desc = birth_place_desc
|
90
|
+
@death_place_desc = death_place_desc
|
91
|
+
@name_variants = name_variants
|
92
|
+
@performances = []
|
93
|
+
end
|
94
|
+
|
95
|
+
# @!method death_place_desc
|
96
|
+
# Returns the description of the place where the artist died.
|
97
|
+
# @return [String] the description of the death place.
|
98
|
+
def death_place_desc
|
99
|
+
@death_place_desc || death_place&.label
|
100
|
+
end
|
101
|
+
|
102
|
+
# @!method birth_place_desc
|
103
|
+
# Returns the description of the place where the artist was born.
|
104
|
+
# @return [String] the description of the birth place.
|
105
|
+
def birth_place_desc
|
106
|
+
@birth_place_desc || birth_place&.label
|
107
|
+
end
|
108
|
+
|
109
|
+
# @!method update(**key_values)
|
110
|
+
# Updates the artist's attributes with the given key-value pairs.
|
111
|
+
# @param key_values [Hash] the attributes to update.
|
112
|
+
def update(**key_values)
|
113
|
+
key_values.each do |key, value|
|
114
|
+
send(:"#{key}=", value)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# @!method performances
|
119
|
+
# Returns a collection of the artist's performances.
|
120
|
+
# @return [Performance::Collection] the collection of performances.
|
121
|
+
def performances
|
122
|
+
Performance::Collection.new(@performances)
|
123
|
+
end
|
124
|
+
|
125
|
+
# @!method public_url
|
126
|
+
# Returns the public URL of the artist's profile.
|
127
|
+
# @return [String] the public URL.
|
128
|
+
def public_url
|
129
|
+
"https://research.rkd.nl/nl/detail/https%3A%2F%2Fdata.rkd.nl%2Fartists%2F#{identifier}"
|
130
|
+
end
|
131
|
+
|
132
|
+
# @!method death_date=(date)
|
133
|
+
# Sets the death date of the artist.
|
134
|
+
# @param date [Date, String] the death date to set.
|
135
|
+
def death_date= date
|
136
|
+
@death_date = parse_date(date)
|
137
|
+
end
|
138
|
+
|
139
|
+
# @!method birth_date=(date)
|
140
|
+
# Sets the birth date of the artist.
|
141
|
+
# @param date [Date, String] the birth date to set.
|
142
|
+
def birth_date= date
|
143
|
+
@birth_date = parse_date(date)
|
144
|
+
end
|
145
|
+
|
146
|
+
# @!method to_partial_path
|
147
|
+
# Returns the partial path for rendering the artist in Rails views.
|
148
|
+
# @return [String] the partial path.
|
149
|
+
def to_partial_path
|
150
|
+
"rkd/artists/artist"
|
151
|
+
end
|
152
|
+
|
153
|
+
# @!method to_param
|
154
|
+
# Returns the identifier of the artist for use in URLs (mostly for rails)
|
155
|
+
# @return [String] the identifier.
|
156
|
+
def to_param
|
157
|
+
identifier
|
158
|
+
end
|
159
|
+
|
160
|
+
# @!method enrich!
|
161
|
+
# Enriches the artist's data by fetching additional information from the SPARQL endpoint
|
162
|
+
# @raise [RKD::Artist::NotFoundError] if no data is found for the artist.
|
163
|
+
def enrich!
|
164
|
+
json = Query::Sparql.find(identifier)
|
165
|
+
|
166
|
+
death_data = json.select { |a| a["property"] == "http://www.cidoc-crm.org/cidoc-crm/P100i_died_in" }
|
167
|
+
birth_data = json.select { |a| a["property"] == "http://www.cidoc-crm.org/cidoc-crm/P98i_was_born" } # different placeRefs
|
168
|
+
|
169
|
+
death_places_data = extract_places_data(death_data).first
|
170
|
+
birth_places_data = extract_places_data(birth_data).first
|
171
|
+
|
172
|
+
@death_place = Place.new(**death_places_data) if death_places_data
|
173
|
+
self.death_date = [death_data.first["begin"], death_data.first["end"]].compact.max_by(&:length) if death_data.first
|
174
|
+
|
175
|
+
@birth_place = Place.new(**birth_places_data) if birth_places_data
|
176
|
+
self.birth_date = [birth_data.first["begin"], birth_data.first["end"]].compact.max_by(&:length) if birth_data.first
|
177
|
+
|
178
|
+
@name = json.select { |row| row["property"] == "http://www.w3.org/2000/01/rdf-schema#label" }.map { |row| row["value"] }.first
|
179
|
+
|
180
|
+
performances_data = json.select { |row| row["property"] == "http://www.cidoc-crm.org/cidoc-crm/P14i_performed" }.group_by { |row| row["value"] }
|
181
|
+
@performances = performances_data.map do |perf_id, values|
|
182
|
+
parse_performance_data(perf_id, values)
|
183
|
+
end.compact
|
184
|
+
|
185
|
+
type_data = json.select { |a| a["property"] == "http://www.cidoc-crm.org/cidoc-crm/P2_has_type" }.map { |row| {label: row["prefLabel"], ref: row["value"]} }.select { |a| a[:label] }
|
186
|
+
@types = type_data.map { |type_datum| RKD::Type.new(**type_datum) }
|
187
|
+
|
188
|
+
unlabeled_types = json.select { |a| a["property"] == "http://www.cidoc-crm.org/cidoc-crm/P2_has_type" }.map { |row| {label: row["prefLabel"], ref: row["value"]} }.select { |a| !a[:label] }.map { |row| row[:ref] }
|
189
|
+
|
190
|
+
if unlabeled_types.delete("http://vocab.getty.edu/aat/300189559")
|
191
|
+
@gender = "male"
|
192
|
+
elsif unlabeled_types.delete("http://vocab.getty.edu/aat/300189557")
|
193
|
+
@gender = "female"
|
194
|
+
end
|
195
|
+
|
196
|
+
type_data = json.select { |a| a["property"] == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" }.map { |row| {label: row["value"].sub(/http:\/\/www\.cidoc-crm\.org\/cidoc-crm\/[A-E]\d+_/, "").sub("_", " "), ref: row["value"]} }.select { |a| a[:label] }
|
197
|
+
@types += type_data.map { |type_datum| RKD::Type.new(**type_datum) }
|
198
|
+
|
199
|
+
p unlabeled_types if unlabeled_types.any?
|
200
|
+
|
201
|
+
@updated_at = begin
|
202
|
+
DateTime.parse json.find { |a| a["property"] == "http://www.w3.org/ns/prov#generatedAtTime" }["value"]
|
203
|
+
rescue Date::Error
|
204
|
+
rescue NoMethodError
|
205
|
+
if json == []
|
206
|
+
raise RKD::Artist::NotFoundError, "Nothing found for id #{identifier}"
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
private
|
212
|
+
|
213
|
+
# details are not expected to be updated
|
214
|
+
attr_writer :id, :name, :identifier, :gender, :birth_place_desc, :death_place_desc
|
215
|
+
|
216
|
+
def extract_places_data(responses)
|
217
|
+
grouped_responses = responses.group_by { |a| [a["placePoint"], a["placeLabel"]] }
|
218
|
+
grouped_responses
|
219
|
+
.map { |k, v| [k, v.map { |a| a["placeRef"] }] }
|
220
|
+
.map { |r| {point: r[0][0], label: r[0][1], refs: r[1]} }
|
221
|
+
end
|
222
|
+
|
223
|
+
def parse_performance_data(perf_id, values)
|
224
|
+
if perf_id.start_with?("https://data.rkd.nl/artists/#{identifier}/study") || perf_id.start_with?("https://data.rkd.nl/artists/#{identifier}/educate")
|
225
|
+
label = values.first["studyLabel"] || values.first["referenceContent"]
|
226
|
+
return if label.nil?
|
227
|
+
institution = Institution.initialize_from_label(label)
|
228
|
+
institution&.id = values.map { |a| a["range"] }.compact.first
|
229
|
+
place = institution&.place || Place.new(label: values.first["studyLabel"])
|
230
|
+
comments = values.map { |a| a["referenceContent"] }.uniq
|
231
|
+
date_span = DateSpan.parse(comments.first)
|
232
|
+
RKD::Performance::Study.new(place:, date_span:, institution:, comments: comments.join("\n\n"))
|
233
|
+
elsif perf_id.start_with?("https://data.rkd.nl/artists/#{identifier}/award")
|
234
|
+
# ignoring for now
|
235
|
+
elsif perf_id.start_with?("https://data.rkd.nl/artists/#{identifier}/work")
|
236
|
+
place_data = extract_places_data(values).first
|
237
|
+
place = Place.new(**place_data)
|
238
|
+
ts_begin = values.first["tookPlaceAtTimeSpanBegin"]
|
239
|
+
ts_end = values.first["tookPlaceAtTimeSpanEnd"]
|
240
|
+
date_span = RKD::DateSpan.new(ts_begin, ts_end)
|
241
|
+
RKD::Performance::Work.new(place:, date_span:)
|
242
|
+
else
|
243
|
+
place_data = extract_places_data(values).first
|
244
|
+
place = Place.new(**place_data)
|
245
|
+
ts_begin = values.first["tookPlaceAtTimeSpanBegin"]
|
246
|
+
ts_end = values.first["tookPlaceAtTimeSpanEnd"]
|
247
|
+
date_span = RKD::DateSpan.new(ts_begin, ts_end)
|
248
|
+
RKD::Performance.new(place:, date_span:) unless place.nilly? || date_span.nilly?
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|