1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
import sys
import json
import itertools
import fatcat_client
from fatcat.importer_common import FatcatImporter
class FatcatCrossrefImporter(FatcatImporter):
def __init__(self, host_url, issn_map_file, create_containers=True):
super().__init__(host_url, issn_map_file)
self.create_containers = create_containers
def parse_crossref_dict(self, obj):
"""
obj is a python dict (parsed from json).
returns a ReleaseEntity
"""
# This work is out of scope if it doesn't have authors or a title
if (not 'author' in obj) or (not 'title' in obj):
return None
# Other ways to be out of scope (provisionally)
if ((not 'type' in obj) or (not 'container-title' in obj) or
len(obj['container-title']) < 1):
return None
# contribs
contribs = []
for i, am in enumerate(obj['author']):
creator_id = None
if 'ORCID' in am.keys():
creator_id = self.lookup_orcid(am['ORCID'].split('/')[-1])
# Sorry humans :(
if am.get('given') and am.get('family'):
raw_name = "{} {}".format(am['given'], am['family'])
elif am.get('family'):
raw_name = am['family']
else:
# TODO: defaults back to a pseudo-null value
raw_name = am.get('given', '<blank>')
contribs.append(fatcat_client.ReleaseContrib(
creator_id=creator_id,
index=i+1,
raw_name=raw_name,
role="author"))
# container
issn = obj.get('ISSN', [None])[0]
issnl = self.issn2issnl(issn)
container_id = None
if issnl:
container_id = self.lookup_issnl(issnl)
publisher = obj.get('publisher')
ce = None
if container_id is None and self.create_containers and issnl != None:
ce = fatcat_client.ContainerEntity(
issnl=issnl,
publisher=publisher,
name=obj['container-title'][0])
# references
refs = []
for i, rm in enumerate(obj.get('reference', [])):
try:
year = int(rm.get('year'))
if year > 2025 or year < 1000:
# NOTE: will need to update/config in the future!
# NOTE: are there crossref works with year < 1000?
return None
except:
year = None
extra = dict(crossref=rm)
if rm.get('DOI') != None:
extra['doi'] = rm.get('DOI').lower()
refs.append(fatcat_client.ReleaseRef(
index=i+1,
# doing lookups would be a second import pass
target_release_id=None,
# unreliable for crossref: key=rm['key'].split('|')[-1],
year=year,
container_title=rm.get('volume-title'),
title=rm.get('title'),
locator=rm.get('first-page'),
# TODO: just dump JSON somewhere here?
extra=dict(crossref=rm)))
# abstracts
abstracts = []
if obj.get('abstract') != None:
abstracts.append(fatcat_client.ReleaseEntityAbstracts(
mimetype="application/xml+jats",
content=obj.get('abstract')))
# release
extra = dict(crossref={
'links': obj.get('link', []),
'subject': obj.get('subject'),
'type': obj['type'],
'license': obj.get('license', [dict(URL=None)])[0]['URL'] or None,
'alternative-id': obj.get('alternative-id', [])})
re = fatcat_client.ReleaseEntity(
work_id=None,
title=obj['title'][0],
contribs=contribs,
refs=refs,
container_id=container_id,
release_type=obj['type'],
doi=obj['DOI'].lower(),
release_date=obj['created']['date-time'],
issue=obj.get('issue'),
volume=obj.get('volume'),
pages=obj.get('page'),
abstracts=abstracts,
extra=extra)
return (re, ce)
def create_row(self, row, editgroup_id=None):
if row is None:
return
obj = json.loads(row)
entities = self.parse_crossref_dict(obj)
if entities is not None:
(re, ce) = entities
re.editgroup_id = editgroup_id
if ce is not None:
ce.editgroup_id = editgroup_id
container = self.api.create_container(ce)
re.container_id = container.ident
self._issnl_id_map[ce.issnl] = container.ident
self.api.create_release(re)
def create_batch(self, batch, editgroup_id=None):
"""Current work/release pairing disallows batch creation of releases.
Could do batch work creation and then match against releases, but meh."""
release_batch = []
for row in batch:
if row is None:
continue
obj = json.loads(row)
entities = self.parse_crossref_dict(obj)
if entities is not None:
(re, ce) = entities
re.editgroup_id = editgroup_id
if ce is not None:
ce.editgroup_id = editgroup_id
container = self.api.create_container(ce)
re.container_id = container.ident
self._issnl_id_map[ce.issnl] = container.ident
release_batch.append(re)
self.api.create_release_batch(release_batch, autoaccept="true", editgroup=editgroup_id)
|