Skip to content

Commit

Permalink
Merge pull request #57 from ontoportal-lirmm/pr/feature/add-a-script-…
Browse files Browse the repository at this point in the history
…to-import-ontologies

Add a script to import an ontology and its latest_submission from another portal
  • Loading branch information
jvendetti authored Jul 29, 2022
2 parents 77f7f9a + 30f702e commit 5683c12
Showing 1 changed file with 172 additions and 0 deletions.
172 changes: 172 additions & 0 deletions bin/ncbo_ontology_import
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



0 comments on commit 5683c12

Please sign in to comment.