append = pack
[use]
# URLConnect
plugin = basics
plugin = analytics
[env]
path = number2labelDR
value = fix({"01": "DR01 Ile-de-France Villejuif","02": "DR02 Paris-Centre","03": "DR01 Ile-de-France Villejuif","04": "DR04 Ile-de-France Gif-sur-Yvette","05": "DR05 Ile-de-France Meudon","06": "DR06 Centre Est","07": "DR07 Rhône Auvergne","08": "DR08 Centre Limousin Poitou Charente","10": "DR10 Alsace","11": "DR11 Alpes","12": "DR12 Provence et Corse","20": "DR20 Côte d'Azur","13": "DR13 Occitanie Est","14": "DR14 Occitanie Ouest","15": "DR15 Aquitaine","16": "DR16 Paris-Normandie","17": "DR17 Bretagne et Pays de la Loire","18": "DR18 Hauts-de-France","19": "DR16 Paris-Normandie"})
path = weekNumber
value = thru(() => new Date()).thru(currentDate => Math.floor((currentDate - (new Date(currentDate.getFullYear(), 0, 1)))/(24 * 60 * 60 * 1000))).thru(days => Math.ceil(days / 7))
path = dayNumber
value = thru(() => Math.floor((Date.now() - new Date(new Date().getFullYear(), 0, 0)) / 86400000))
# Permet de choisir la durée du cache :
# - env('weekNumber') : permet de garder les données en cache pour une semaine,
# - env('dayNumber') : permet de garder les données en cache pour une journée,
# - forever : permet de garder les données en cache pour toujours
[env]
path = cacheSalt
value = env('weekNumber')
[unpack]
# Quand les RNSR ne sont pas fournis dans authors.*.affiliations.*.rnsr
# on utilise le Web Service qui les met au même niveau dans wsRnsr
# Récupère les infos Loterre 2XK
[assign]
path = ws.loterre2xk
value = get("codesRnsr").castArray().map((itemcodesRnsr, indice) => ({indice, itemcodesRnsr, codeRNSR: itemcodesRnsr, institut: itemcodesRnsr, publicationDate: self.publicationYear }))
[expand]
path = ws.loterre2xk
[expand/exploding]
[expand/expand]
path = value.itemcodesRnsr
size = 100
cacheName = fix(`${env('cacheSalt')}-04-2xk-identify`)
[expand/expand/URLConnect]
url = https://loterre-resolvers.services.istex.fr/v1/2XK/identify
timeout = 120000
noerror = true
[expand/assign]
path = value.institut
value = get('value.institut').append(`|${self.value.publicationDate}`)
[expand/expand]
path = value.institut
size = 100
file = ./04-enrich-rnsrByYear.ini
cacheName = fix(`${env('cacheSalt')}-04-rnsr-year-instituts-cnrs`)
[expand/assign]
path = value.label
value = get('value.itemcodesRnsr.prefLabel@fr', 'n/a')
path = value.labelNormalized
value = get('value.itemcodesRnsr.prefLabel@fr', 'n/a').thru(item => String(item).normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toUpperCase())
path = value.dr
value = get("value.itemcodesRnsr.delegationRegionale_dep").castArray().compact().map(n => _.get(env("number2labelDR"), n, `unknow ${n}` ))
[expand/aggregate]
[assign]
path = codesRnsr
value = get("ws.loterre2xk").castArray().map('codeRNSR')
path = laboIntitule
value = get("ws.loterre2xk").castArray().map('label')
path = delegationsRegionales
value = get("ws.loterre2xk").castArray().map('dr')
path = institutCnrs
value = get("ws.loterre2xk").castArray().map('institut')
# S'il y a au moins un institut, il y a au moins une affiliation CNRS
path = isCnrs
value = get("ws.loterre2xk").castArray().map('institut').thru(array => Boolean(array.length))
; [debug]
; path = codesRnsr
; path = laboIntitule
; path = delegationsRegionales
; path = institutCnrs
; path = isCnrs
[assign]
path=wsOpenalex
value = get("doi")
[swing]
test = get("wsOpenalex").isEmpty()
reverse = true
[swing/expand]
path = wsOpenalex
size = 100
[swing/expand/URLConnect]
url = https://biblio-tools.services.istex.fr/v1/openalex/works/expand
timeout = 90007
noerror = true
# Données Open Access host type modifiées à partir d'un champ fulltext, si hal est présent
#Transformer des données inconnues de 'HostType' en repository si absence d'un DOI mais présence de Hal dans 'fulltext'
[assign]
path = is_retracted
value = get("wsOpenalex.is_retracted").thru(bool => bool === true ? "Oui" : "Non")
[assign]
path = oaLocationsUnpaywallHal
value = get("enrichments.openAccess.unpaywall.oaLocations").map("hostType").concat(self.fulltextUrl && self.fulltextUrl.includes("hal") ? ["repository"] : []).filter((value, index, collection) => !(value === "OA - Inconnu" && collection[index + 1] === "repository")).uniq()
#Transformer des données inconnues en "green" si absence d'un DOI mais présence de "repository" dans 'oaLocationsUnpaywallHal'
[assign]
path = oaStatusUnpaywallHal
value = get("enrichments.openAccess.unpaywall.oaStatus","OA - Inconnu").concat(self.oaLocationsUnpaywallHal.includes("repository") ? "repository" : []).reduce((acc, val, index, arr) => {return (["OA - Inconnu", "OA - Non", "closed"].includes(val) && arr.includes("repository"))? ["green"]: acc.concat(val)}, []).head().capitalize().replace("Oa - inconnu","OA - Inconnu")
##Transformer des données inconnues en OA-Oui si absence d'un DOI mais présence de "green" dans 'oaStatusUnpaywallHal'
[assign]
path = isOaUnpaywallHal
value=get("oaStatusUnpaywallHal").thru(v=>v ==="OA - Inconnu" ? "OA - Inconnu" : v==="closed" ? "OA - Non" : "OA - Oui" )
#On traduit les voies d'acces. Sort pour placer "publisher" avant "repository", replace puis si les 2 valeurs sont présentes, on remplace par "commun"
[assign]
path = hostTypeUnpaywallHal
value = get("oaLocationsUnpaywallHal").map(v => v === "repository" ? "Archive seule" : v === "publisher" ? "Editeur seul" : v==="OA - Inconnu" ? v :v).thru(arr=>_.size(arr)===2 ? "Commun" : _.size(arr)===0 ? "OA - Non" : arr).toString()
#on crée un nouveau champ où l'on récupère les valeurs de "apc_list/value". Si value = 0 alors la publi est diamant. On remplace donc "0" par "diamond" et efface tout le reste. On concatène ensuite avec enrichments/openAccess/unpaywall/oaStatus qui donne les couleurs de l'OA. Puis on retire "gold" lorsqu'il est associé à "diamond"
[assign]
path = oaStatusUnpaywallOpenalex
value=get("wsOpenalex.open_access/oa_status").thru(v=>v==="diamond" ? "Diamond" : _.capitalize(self.enrichments.openAccess.unpaywall.oaStatus)).replace(/^$/,"OA - Inconnu")
#on crée un nouveau champ où l'on cumule les nouvelles données de 'oaStatusUnpaywallOpenalex' et 'oaStatusUnpaywallHal'
[assign]
path = oaStatusUnpaywallOpenalexHal
value = get("wsOpenalex.open_access/oa_status").thru(v=>v==="diamond" ? "Diamond" : self.oaStatusUnpaywallHal)
#Transformations spécifiques pour créer des valuers compatibles avec VEga-lite pour la création de graphiques
[assign]
path = graphSourceEditeurIsOa
value = get("enrichments.openAccess.unpaywall.isOa").replace(/^((?!Oui).)*$/,"null").prepend("OA=").append((";TypeAcces="+self.hostTypeUnpaywallHal).replace(/Commun|Editeur seul/g,"Editeur").replace(/OA - Non|Archive seule|OA - Inconnu/g,"null"))
[assign]
path = graphSourceEditeurIsOaHal
value = get("isOaUnpaywallHal").replace(/^((?!Oui).)*$/,"null").prepend("OA=").append((";TypeAcces="+self.hostTypeUnpaywallHal).replace(/Commun|Editeur seul/g,"Editeur").replace(/OA - Non|Archive seule|OA - Inconnu/g,"null"))
#On détermine l'ordre de provenance des notices composants la notice Conditor
[assign]
path = sourceOfMergedRecords
value = get("sourceUidChain").replace(/\$.*?!/g,"!").split("!").compact()
#On concatène 'volume', 'issue' et 'pages.range' dans un seul champ
#Récupère les fulltext d'unpaywall si le champs 'fulltexturl' (qui vient de conditor) est nul
[assign]
path = fulltextUrl
value = get("fulltextUrl").castArray().compact().thru(v => _.isEmpty(v) ? self.enrichments.openAccess.unpaywall.oaLocations.filter(item => item.hostType === "repository" && item.isBest===true).map(item => item.url) : v)
#Homogénéise les types de document
[assign]
path = documentType
value = get("originalGenre").trim()
[expand]
path = documentType
size = 100
file = ./04-enrich-doctype.ini
cacheName = fix(`${env('cacheSalt')}-04-homogenize-document-type-json`)
# Si le WS renvoie un "n/a"
[swing]
test = get("documentType").isEqual("n/a")
# On l'écrase avec la valeur de "originalGenre"
[swing/assign]
path = documentType
value = get("originalGenre").trim()
# Homogénéise les sources
[assign]
path = source
value = get("host.title",_.get(self,"host.conference.name")).trim()
# si les champs 'host.title' et 'host.conference.name' ne sont pas vides
[expand]
path = source
size = 100
file = ./04-enrich-source.ini
cacheName = fix(`${env('cacheSalt')}-04-homogenize-source-json`)
[swing]
test = get("source").isEqual("n/a")
[swing/assign]
path = source
value = get("host.title",_.get(self,"host.conference.name")).trim()
# si le champ "source" issu du WS est "n/a"
# Traitement des éditeurs
[assign]
path = ws.ApilRacineDoiPublisher
value = get("doi").split('/').filter(i => i.match(/^10./)).pop()
[expand]
path = ws.ApilRacineDoiPublisher
size = 1
cacheName = fix(`${env('cacheSalt')}-04-api-crossref-prefixes-expand`)
[expand/URLFetch]
target = value
url = fix('https://api.crossref.org/prefixes/').append(self.value)
json = true
timeout = 60000
noerror = true
retries = 2
[expand/assign]
path = value
value = get('value.message.name', 'n/a')
# Dans un champ temporaire, récupérer la valeur host.publisher si elle est présente, sinon récupérer celle du WS DOI.
[assign]
path = tmp.publisher
value = get("host.publisher",_.get(self,"ws.ApilRacineDoiPublisher"))
# Homogénéise l'éditeur
[assign]
path = publisher
value = get("tmp.publisher").trim()
[expand]
path = publisher
size = 100
file = ./04-enrich-publisher.ini
cacheName = fix(`${env('cacheSalt')}-04-homogenize-publisher-json`)
# Si host.publisher existe et que le publisher vaut n/a,
[swing]
test = has("host.publisher")
test = get("publisher").isEqual("n/a")
# On l'écrase avec la valeur de host.publisher
[swing/assign]
path = publisher
value = get("host.publisher")
# Enrichissements pays
[assign]
path = ws.libpostal
value = get("authors") \
.flatMap("affiliations") \
.map("address").uniq() \
.map((address, id) => ({ \
id, \
value: address \
}))
[map]
path = ws.libpostal
[map/expand]
path = value
size = 100
cacheName = fix(`${env('cacheSalt')}-04-address-expand`)
[map/expand/URLConnect]
url = https://affiliations-tools.services.istex.fr/v1/addresses/parse
timeout = 90007
noerror = true
[map/expand/assign]
path = value.value.address
value = get('value.id')
path = value.value.country
value = get('value.value.country').replace(/\W/g, ' ').trim()
[map/expand/assign]
path = value
value = get('value.value')
[map/expand/expand]
path = value.country
size = 10
cacheName = fix(`${env('cacheSalt')}-04-country-expand`)
[map/expand/expand/URLConnect]
url = https://loterre-resolvers.services.istex.fr/v1/9SD/identify
timeout = 90008
[map/exchange]
value = get('value')
# TODO: si champ state, on est aux États-Unis (United States of America)
[assign]
path = codeISO
value = get("ws.libpostal").castArray().filter(Boolean) \
.map(n => n.country?.cartographyCode) \
.uniq().filter(Boolean)
path = countries
value = get("ws.libpostal").castArray().filter(Boolean) \
.map(n => n.country?.["prefLabel@en"]) \
.uniq().filter(Boolean)
# Suppression des champs non voulus
[exchange]
value = omit(['tmp','ws','originalGenre','localRef','pii','host'])