-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #57 from ontoportal-lirmm/pr/feature/add-a-script-…
…to-import-ontologies Add a script to import an ontology and its latest_submission from another portal
- Loading branch information
Showing
1 changed file
with
172 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
#!/usr/bin/env ruby | ||
|
||
$0 = 'ncbo_cron' | ||
|
||
# Exit cleanly from an early interrupt | ||
Signal.trap('INT') { exit 1 } | ||
|
||
# Setup the bundled gems in our environment | ||
require 'bundler/setup' | ||
# redis store for looking up queued jobs | ||
require 'redis' | ||
|
||
require_relative '../lib/ncbo_cron' | ||
require_relative '../config/config' | ||
require 'net/http' | ||
|
||
# Script for importing ontologies + latest_submission into ontoportal appliance | ||
|
||
|
||
require 'optparse' | ||
ontologies_acronyms = '' | ||
ontology_source = '' | ||
source_api = '' | ||
username = '' | ||
opt_parser = OptionParser.new do |opts| | ||
opts.banner = 'Usage: ncbo_ontology_import [options]' | ||
opts.on('-o', '--ontology ACRONYM', 'Ontologies acronyms which we want to import (separated by comma)') do |acronym| | ||
ontologies_acronyms = acronym | ||
end | ||
|
||
opts.on('--from url', 'The ontoportal api url source of the ontology') do |url| | ||
ontology_source = url.to_s | ||
end | ||
|
||
opts.on('--from-api api', 'An apikey to acces the ontoportal api') do |api| | ||
source_api = api.to_s | ||
end | ||
|
||
opts.on('--admin-user username', 'The target admin user that will submit the ontology') do |user| | ||
username = user.to_s | ||
end | ||
# Display the help screen, all programs are assumed to have this option. | ||
opts.on( '-h', '--help', 'Display this screen') do | ||
puts opts | ||
exit | ||
end | ||
end | ||
opt_parser.parse! | ||
|
||
# URL of the API and APIKEY of the Ontoportal we want to import data FROM | ||
SOURCE_API = ontology_source | ||
SOURCE_APIKEY = source_api | ||
|
||
|
||
# The username of the user that will have the administration rights on the ontology on the target portal | ||
TARGETED_PORTAL_USER = username | ||
|
||
# The list of acronyms of ontologies to import | ||
ONTOLOGIES_TO_IMPORT = ontologies_acronyms.split(',') || [] | ||
|
||
|
||
def get_user(username) | ||
user = LinkedData::Models::User.find(username).first | ||
raise "The user #{username} does not exist" if user.nil? | ||
user.bring_remaining | ||
end | ||
|
||
|
||
# A function to create a new ontology (if already Acronym already existing on the portal it will return HTTPConflict) | ||
def create_ontology(ont_info) | ||
|
||
new_ontology = LinkedData::Models::Ontology.new | ||
|
||
new_ontology.acronym = ont_info['acronym'] | ||
new_ontology.name = ont_info['name'] | ||
new_ontology.administeredBy = [USER] | ||
if ont_info['viewingRestriction'] == 'private' | ||
# In case of private ontology (acl: list of user that have the right to see the ontology) | ||
new_ontology.viewingRestriction = 'private' | ||
new_ontology.acl = [USER] | ||
end | ||
new_ontology | ||
end | ||
|
||
# A function that take the submission informations from the source Ontoportal to create a new submission | ||
# 2 possibilities: | ||
# - the source Ontoportal pulls the ontology from an URL (pullLocation is filled), in this case we directly pull from this URL | ||
# - Or it stores it directly in the portal, in this case we pull it from the portal download link | ||
def upload_submission(sub_info, ontology) | ||
new_submission = LinkedData::Models::OntologySubmission.new | ||
# Check if the source BioPortal is pulling the ontology from an URL | ||
# If yes then we will pull the ontology from this place (allow auto update of the ontology when the ontology is changed in its source URL) | ||
if sub_info['pullLocation'].nil? | ||
sub_info['pullLocation'] = "#{sub_info['ontology']['links']['download']}?apikey=#{SOURCE_APIKEY}" | ||
end | ||
|
||
# Build the json body | ||
# hasOntologyLanguage options: OWL, UMLS, SKOS, OBO | ||
# status: alpha, beta, production, retired | ||
attr_to_reject = %w[id submissionStatus hasOntologyLanguage metrics ontology @id @type contact] | ||
to_copy = sub_info.select do |k,v| | ||
!v.nil? && !v.is_a?(Hash) && !v.to_s.empty? && !attr_to_reject.include?(k) | ||
end | ||
to_copy["ontology"] = ontology | ||
to_copy["contact"] = [LinkedData::Models::Contact.where(email: USER.email).first] | ||
to_copy["hasOntologyLanguage"] = LinkedData::Models::OntologyFormat.where(acronym: sub_info["hasOntologyLanguage"]).first | ||
|
||
to_copy.each do |key, value| | ||
attribute_settings = new_submission.class.attribute_settings(key.to_sym) | ||
|
||
if attribute_settings | ||
if attribute_settings[:enforce]&.include?(:date_time) | ||
value = DateTime.parse(value) | ||
elsif attribute_settings[:enforce]&.include?(:uri) && attribute_settings[:enforce]&.include?(:list) | ||
value = value.map { |v| RDF::IRI.new(v) } | ||
elsif attribute_settings[:enforce]&.include?(:uri) | ||
value = RDF::IRI.new(value) | ||
end | ||
end | ||
|
||
new_submission.send("#{key}=", value) | ||
end | ||
|
||
new_submission | ||
end | ||
|
||
|
||
USER = get_user username | ||
#get apikey for admin user | ||
TARGET_APIKEY = USER.apikey | ||
|
||
SOURCE_APIKEY == '' && abort('--from-api has to be set') | ||
SOURCE_API == '' && abort('--from has to be set') | ||
|
||
def result_log(ressource, errors) | ||
if !errors | ||
puts "#{ressource} imported successfully" | ||
else | ||
puts errors | ||
end | ||
end | ||
|
||
# Go through all ontologies acronym and get their latest_submission informations | ||
ONTOLOGIES_TO_IMPORT.each do |ont| | ||
sub_info = JSON.parse(Net::HTTP.get(URI.parse("#{SOURCE_API}/ontologies/#{ont}/latest_submission?apikey=#{SOURCE_APIKEY}&display=all"))) | ||
puts "Import #{ont} " , | ||
"From #{SOURCE_API}" | ||
# if the ontology is already created then it will return HTTPConflict, no consequences | ||
raise "The ontology #{ont} does not exist" if sub_info['ontology'].nil? | ||
new_ontology = create_ontology(sub_info['ontology']) | ||
errors = nil | ||
if new_ontology.valid? | ||
new_ontology.save | ||
else | ||
errors = new_ontology.errors | ||
new_ontology = nil | ||
end | ||
result_log ont, errors | ||
|
||
new_ontology ||= LinkedData::Models::Ontology.where(acronym: ont).first | ||
new_submission = upload_submission(sub_info, new_ontology) | ||
if new_submission.valid? | ||
new_submission.save | ||
errors = nil | ||
else | ||
errors = new_submission.errors | ||
end | ||
result_log(sub_info["id"], errors) | ||
end | ||
|
||
|
||
|