diff --git a/config/config.rb.sample b/config/config.rb.sample index d3e9f9e08..7539c8d8a 100644 --- a/config/config.rb.sample +++ b/config/config.rb.sample @@ -92,38 +92,6 @@ begin link: 'https://www.googleapis.com/oauth2/v3/userinfo' } } - - config.ui_name = 'Bioportal' - config.title = 'NCBO BioPortal' - config.description = "The world's most comprehensive repository of biomedical ontologies" - config.color = '#234979' - config.logo = '' - config.fundedBy = [ - { - img_src: 'https://identity.stanford.edu/wp-content/uploads/sites/3/2020/07/block-s-right.png', - url: 'https://www.stanford.edu', - - }, - { - img_src: 'https://ontoportal.org/images/logo.png', - url: 'https://ontoportal.org/', - } - ] - config.federated_portals = { - 'agroportal' => { - api: 'http://data.agroportal.lirmm.fr', - ui: 'http://agroportal.lirmm.fr', - apikey: '1cfae05f-9e67-486f-820b-b393dec5764b', - color: '#1e2251' - }, - 'bioportal' => { - api: 'http://data.bioontology.org', - ui: 'http://bioportal.bioontology.org', - apikey: '4a5011ea-75fa-4be6-8e89-f45c8c84844e', - color: '#234979' - }, - - } end rescue NameError => e binding.pry diff --git a/config/schemes/semantic_artefact_catalog.yml b/config/schemes/semantic_artefact_catalog.yml index 06ced74e9..6451b1100 100644 --- a/config/schemes/semantic_artefact_catalog.yml +++ b/config/schemes/semantic_artefact_catalog.yml @@ -63,7 +63,12 @@ fundedBy: helpText: "Founder of the catalog" example: '' enforcedValues: [img_src: "", url: "" ] - default: [] + default: [ + { + img_src: 'https://ontoportal.org/images/logo.png', + url: 'https://ontoportal.org/' + } + ] federated_portals: display: "general" @@ -71,7 +76,15 @@ federated_portals: helpText: "The Federated portal" example: '' enforcedValues: [name: "", api: "", ui: "", apikey: "", color: "" ] - default: [] + default: [ + { + name: 'agroportal', + api: 'http://data.agroportal.lirmm.fr', + ui: 'http://agroportal.lirmm.fr', + apikey: "DUMMY_API_KEY_123456", + color: '#3cb371' + } + ] homepage: display: "general" diff --git a/lib/ontologies_linked_data/concerns/semantic_artefact/attribute_fetcher.rb b/lib/ontologies_linked_data/concerns/semantic_artefact/attribute_fetcher.rb index 0a6d18c4e..84b0b3c41 100644 --- a/lib/ontologies_linked_data/concerns/semantic_artefact/attribute_fetcher.rb +++ b/lib/ontologies_linked_data/concerns/semantic_artefact/attribute_fetcher.rb @@ -13,12 +13,25 @@ def bring(*attributes) hash[model][attr] = mapped_attr end + populate_from_self(grouped_attributes[self.class]) if grouped_attributes[self.class].any? fetch_from_ontology(grouped_attributes[:ontology]) if grouped_attributes[:ontology].any? fetch_from_submission(grouped_attributes[:ontology_submission]) if grouped_attributes[:ontology_submission].any? fetch_from_metrics(grouped_attributes[:metric]) if grouped_attributes[:metric].any? end private + + def populate_from_self(attributes) + attributes.each_key do |attr| + if self.class.handler?(attr) + send(attr) + else + value = self.class.default(attr) + value = value.call(self) if value.is_a?(Proc) + send("#{attr}=", value || (respond_to?(attr) ? send(attr) : nil)) + end + end + end def fetch_from_ontology(attributes) return if attributes.empty? @@ -30,21 +43,21 @@ def fetch_from_ontology(attributes) def fetch_from_submission(attributes) return if attributes.empty? - @latest ||= defined?(@ontology) ? @ontology.latest_submission(status: :ready) : @submission - return unless @latest - @latest.bring(*attributes.values) + @submission_to_fetch_from ||= defined?(@submission) ? @submission : defined?(@ontology) ? @ontology.latest_submission(status: :ready) : nil + return unless @submission_to_fetch_from + @submission_to_fetch_from.bring(*attributes.values) attributes.each do |attr, mapped_attr| - self.send("#{attr}=", @latest.send(mapped_attr)) if @latest.respond_to?(mapped_attr) + self.send("#{attr}=", @submission_to_fetch_from.send(mapped_attr)) if @submission_to_fetch_from.respond_to?(mapped_attr) end end def fetch_from_metrics(attributes) return if attributes.empty? - @latest ||= defined?(@ontology) ? @ontology.latest_submission(status: :ready) : @submission - return unless @latest - @latest.bring(metrics: [attributes.values]) + @submission_to_fetch_from ||= defined?(@submission) ? @submission : defined?(@ontology) ? @ontology.latest_submission(status: :ready) : nil + return unless @submission_to_fetch_from + @submission_to_fetch_from.bring(metrics: [attributes.values]) attributes.each do |attr, mapped_attr| - metric_value = @latest.metrics&.respond_to?(mapped_attr) ? @latest.metrics.send(mapped_attr) || 0 : 0 + metric_value = @submission_to_fetch_from.metrics&.respond_to?(mapped_attr) ? @submission_to_fetch_from.metrics.send(mapped_attr) || 0 : 0 self.send("#{attr}=", metric_value) end end diff --git a/lib/ontologies_linked_data/models/agents/agent.rb b/lib/ontologies_linked_data/models/agents/agent.rb index 24601748b..f9848e0be 100644 --- a/lib/ontologies_linked_data/models/agents/agent.rb +++ b/lib/ontologies_linked_data/models/agents/agent.rb @@ -17,22 +17,31 @@ class Agent < LinkedData::Models::Base attribute :affiliations, enforce: %i[Agent list is_organization], namespace: :org, property: :memberOf attribute :creator, type: :user, enforce: [:existence] embed :identifiers, :affiliations - embed_values affiliations: LinkedData::Models::Agent.goo_attrs_to_load + [identifiers: LinkedData::Models::AgentIdentifier.goo_attrs_to_load] - serialize_methods :usages + serialize_methods :usages, :keywords, :groups, :categories, :subjects, :relatedAgents, :affiliatedAgents + embed_values affiliations: [:name, :agentType, :homepage, :acronym, :email, :identifiers] + prevent_serialize_when_nested :usages, :affiliations, :keywords, :groups, :categories, :subjects, :relatedAgents, :affiliatedAgents + write_access :creator access_control_load :creator enable_indexing(:agents_metadata) def embedded_doc - "#{self.name} #{self.acronym} #{self.email} #{self.agentType}" + { + "id": "#{self.id}", + "name": "#{self.name}", + "acronym": "#{self.acronym}", + "email": "#{self.email}", + "agentType": "#{self.agentType}" + }.to_json end def self.load_agents_usages(agents = [], agent_attributes = OntologySubmission.agents_attr_uris) q = Goo.sparql_query_client.select(:id, :property, :agent, :status).distinct.from(LinkedData::Models::OntologySubmission.uri_type).where([:id,LinkedData::Models::OntologySubmission.attribute_uri(:submissionStatus),:status], [:id, :property, :agent]) q = q.filter("?status = <#{RDF::URI.new(LinkedData::Models::SubmissionStatus.id_prefix + 'RDF')}> || ?status = <#{RDF::URI.new(LinkedData::Models::SubmissionStatus.id_prefix + 'UPLOADED')}>") q = q.filter(agent_attributes.map{|attr| "?property = <#{attr}>"}.join(' || ')) + q = q.values(:agent, *agents.map { |agent| RDF::URI(agent.id.to_s)}) data = q.each_solution.group_by{|x| x[:agent]} @@ -57,6 +66,116 @@ def usages(force_update: false) @usages end + def self.load_agents_keywords(agent) + if agent.usages.empty? + keywords = [] + else + q = Goo.sparql_query_client.select(:keywords).distinct.from(LinkedData::Models::OntologySubmission.uri_type).where([:id, :property, :agent], [:id, LinkedData::Models::OntologySubmission.attribute_uri(:keywords), :keywords]) + q = q.filter("?agent = <#{agent.id}>") + q = q.values(:id, *agent.usages.keys.map { |uri| RDF::URI(uri.to_s)}) + + + keywords = q.solutions.map { |solution| solution[:keywords].to_s } + end + agent.instance_variable_set("@keywords", keywords) + agent.loaded_attributes.add(:keywords) + end + def keywords(force_update: false) + self.class.load_agents_keywords(self) if !instance_variable_defined?("@keywords") || force_update + @keywords + end + + def self.load_agents_categories(agent) + if agent.usages.empty? + categories = [] + else + uris = agent.class.strip_submission_id_from_uris(agent.usages.keys) + + q = Goo.sparql_query_client.select(:categories).distinct.from(LinkedData::Models::Ontology.uri_type) + q = q.optional([:id, LinkedData::Models::Ontology.attribute_uri(:hasDomain), :categories]) + q = q.values(:id, *uris) + + categories = q.solutions.map { |solution| solution[:categories] || solution["categories"] }.compact.uniq.reject(&:empty?) + end + agent.instance_variable_set("@categories", categories) + agent.loaded_attributes.add("categories") + end + + def categories + self.class.load_agents_categories(self) + @categories + end + + def self.load_agents_subjects(agent) + if agent.usages.empty? + subjects = [] + else + uris = agent.usages.keys + q = Goo.sparql_query_client.select(:subjects).distinct.from(LinkedData::Models::OntologySubmission.uri_type) + q = q.optional([:id, LinkedData::Models::OntologySubmission.attribute_uri(:hasDomain), :subjects]) + q = q.values(:id, *uris) + + subjects = q.solutions + .map { |solution| solution[:subjects] || solution["subjects"] } + .compact + .map(&:to_s) + .reject(&:empty?) + .uniq + end + agent.instance_variable_set("@subjects", subjects) + agent.loaded_attributes.add("subjects") + end + + def subjects + self.class.load_agents_subjects(self) + @subjects + end + + def self.load_related_agents(agent) + if agent.usages.empty? + relatedAgents = [] + else + q = Goo.sparql_query_client.select(:id, :agent).distinct.from(LinkedData::Models::OntologySubmission.uri_type).where([:id, :property, :agent]) + q = q.filter(OntologySubmission.agents_attr_uris.map{|attr| "?property = <#{attr}>"}.join(' || ')) + q = q.values(:id, *agent.usages.keys.map { |uri| RDF::URI(uri.to_s)}) + relatedAgentsIds = q.each_solution.group_by{|x| x[:agent].to_s} + .reject { |agent_id, _| agent_id == agent.id.to_s } + .transform_values { |solutions| solutions.map { |s| s[:id] } } + # map the previously fetched usages + relatedAgents = self.fetch_agents_data(relatedAgentsIds.keys) + .reject { |ag| ag.id == agent.id } + .each { |agent| agent.usages = relatedAgentsIds[agent.id.to_s].map(&:to_s).uniq } + .map { |agent| agent.to_h.reject { |k, _| [:klass, :aggregates, :unmapped].include?(k) }} + end + agent.instance_variable_set("@relatedAgents", relatedAgents) + agent.loaded_attributes.add(:relatedAgents) + end + + def relatedAgents + self.class.load_related_agents(self) if !instance_variable_defined?("@relatedAgents") + @relatedAgents + end + + def self.load_affiliated_agents(agent) + return nil unless agent.agentType == 'organization' + q = Goo.sparql_query_client.select(:id).distinct.from(LinkedData::Models::Agent.uri_type) + q = q.where([:id, LinkedData::Models::Agent.attribute_uri(:affiliations), :agent]) + q = q.values(:agent, *agent.id) + + affiliatedAgentsIds = q.solutions.map { |solution| solution[:id].to_s }.uniq + affiliatedAgents = self.fetch_agents_data(affiliatedAgentsIds).map { |agent| agent.to_h.reject { |k, _| [:klass, :aggregates, :unmapped].include?(k) }} + + + agent.instance_variable_set("@affiliatedAgents", affiliatedAgents) + agent.loaded_attributes.add(:affiliatedAgents) + + end + + def affiliatedAgents + self.class.load_affiliated_agents(self) if !instance_variable_defined?("@affiliatedAgents") + @affiliatedAgents + end + def unique_identifiers(inst, attr) inst.bring(attr) if inst.bring?(attr) identifiers = inst.send(attr) @@ -83,6 +202,39 @@ def is_organization(inst, attr) [] end + def self.fetch_agents_data(affiliated_agents_ids) + return [] if affiliated_agents_ids.empty? + + agent_ids = affiliated_agents_ids.map(&:to_s).uniq + + q = Goo.sparql_query_client + .select(:id, :name, :acronym, :agentType) + .distinct + .from(LinkedData::Models::Agent.uri_type) + .where( + [:id, LinkedData::Models::Agent.attribute_uri(:name), :name], + [:id, LinkedData::Models::Agent.attribute_uri(:agentType), :agentType] + ) + .optional([:id, LinkedData::Models::Agent.attribute_uri(:acronym), :acronym]) + .values(:id, *agent_ids.map { |uri| RDF::URI(uri.to_s) }) + + q.solutions.map do |agent| + LinkedData::Models::Agent.read_only( + id: agent[:id].to_s, + name: agent[:name].to_s, + acronym: agent[:acronym].to_s, + agentType: agent[:agentType].to_s, + usages: nil + ) + end + end + + def self.strip_submission_id_from_uris(uris) + uris.map do |uri| + cleaned_uri = uri.to_s.sub(%r{/submissions/\d+$}, '') + RDF::URI(cleaned_uri) + end + end end end end diff --git a/lib/ontologies_linked_data/models/mod/hydra_page.rb b/lib/ontologies_linked_data/models/mod/hydra_page.rb new file mode 100644 index 000000000..877b4c9d9 --- /dev/null +++ b/lib/ontologies_linked_data/models/mod/hydra_page.rb @@ -0,0 +1,59 @@ +module LinkedData + module Models + class HydraPage < Goo::Base::Page + + def convert_hydra_page(options, &block) + { + '@id': get_request_path(options), + '@type': 'hydra:Collection', + totalItems: self.aggregate, + itemsPerPage: self.size, + view: generate_hydra_page_view(options, self.page_number, self.total_pages), + member: map { |item| item.to_flex_hash(options, &block) } + } + end + + def self.generate_hydra_context + { + 'hydra': 'http://www.w3.org/ns/hydra/core#', + 'Collection': 'hydra:Collection', + 'member': 'hydra:member', + 'totalItems': 'hydra:totalItems', + 'itemsPerPage': 'hydra:itemsPerPage', + 'view': 'hydra:view', + 'firstPage': 'hydra:first', + 'lastPage': 'hydra:last', + 'previousPage': 'hydra:previous', + 'nextPage': 'hydra:next', + } + end + + private + + def generate_hydra_page_view(options, page, page_count) + request_path = get_request_path(options) + params = options[:request] ? options[:request].params.dup : {} + + build_url = ->(page_number) { + query = Rack::Utils.build_nested_query(params.merge("page" => page_number.to_s)) + request_path ? "#{request_path}?#{query}" : "?#{query}" + } + + { + "@id": build_url.call(page), + "@type": "hydra:PartialCollectionView", + firstPage: build_url.call(1), + previousPage: page > 1 ? build_url.call(page - 1) : nil, + nextPage: page < page_count ? build_url.call(page + 1) : nil, + lastPage: page_count != 0 ? build_url.call(page_count) : build_url.call(1) + } + end + + def get_request_path(options) + request_path = options[:request] ? "#{LinkedData.settings.rest_url_prefix.chomp("/")}#{options[:request].path}" : nil + request_path + end + + end + end +end diff --git a/lib/ontologies_linked_data/models/mod/mod_base.rb b/lib/ontologies_linked_data/models/mod/mod_base.rb new file mode 100644 index 000000000..e1962058c --- /dev/null +++ b/lib/ontologies_linked_data/models/mod/mod_base.rb @@ -0,0 +1,6 @@ +module LinkedData + module Models + class ModBase < LinkedData::Models::Base + end + end +end diff --git a/lib/ontologies_linked_data/models/mod/semantic_artefact.rb b/lib/ontologies_linked_data/models/mod/semantic_artefact.rb index d0df179d4..f822828e7 100644 --- a/lib/ontologies_linked_data/models/mod/semantic_artefact.rb +++ b/lib/ontologies_linked_data/models/mod/semantic_artefact.rb @@ -1,4 +1,5 @@ require 'ontologies_linked_data/models/mod/semantic_artefact_distribution' +require 'ontologies_linked_data/models/mod/semantic_artefact_catalog_record' require 'ontologies_linked_data/models/skos/scheme' require 'ontologies_linked_data/models/skos/collection' require 'ontologies_linked_data/models/skos/skosxl' @@ -7,7 +8,7 @@ module LinkedData module Models - class SemanticArtefact < LinkedData::Models::Base + class SemanticArtefact < LinkedData::Models::ModBase include LinkedData::Concerns::SemanticArtefact::AttributeMapping include LinkedData::Concerns::SemanticArtefact::AttributeFetcher @@ -118,17 +119,16 @@ class SemanticArtefact < LinkedData::Models::Base attribute :ontology, type: :ontology, enforce: [:existence] links_load :acronym - link_to LinkedData::Hypermedia::Link.new("distributions", lambda {|s| "artefacts/#{s.acronym}/distributions"}, LinkedData::Models::SemanticArtefactDistribution.type_uri), - LinkedData::Hypermedia::Link.new("record", lambda {|s| "artefacts/#{s.acronym}/record"}), - LinkedData::Hypermedia::Link.new("resources", lambda {|s| "artefacts/#{s.acronym}/resources"}), - LinkedData::Hypermedia::Link.new("single_resource", lambda {|s| "artefacts/#{s.acronym}/resources/{:resourceID}"}), - LinkedData::Hypermedia::Link.new("classes", lambda {|s| "artefacts/#{s.acronym}/classes"}, LinkedData::Models::Class.uri_type), - LinkedData::Hypermedia::Link.new("concepts", lambda {|s| "artefacts/#{s.acronym}/concepts"}, LinkedData::Models::Class.uri_type), - LinkedData::Hypermedia::Link.new("properties", lambda {|s| "artefacts/#{s.acronym}/properties"}, "#{Goo.namespaces[:metadata].to_s}Property"), - LinkedData::Hypermedia::Link.new("individuals", lambda {|s| "artefacts/#{s.acronym}/classes/roots"}, LinkedData::Models::Class.uri_type), - LinkedData::Hypermedia::Link.new("schemes", lambda {|s| "artefacts/#{s.acronym}/schemes"}, LinkedData::Models::SKOS::Scheme.uri_type), - LinkedData::Hypermedia::Link.new("collection", lambda {|s| "artefacts/#{s.acronym}/collections"}, LinkedData::Models::SKOS::Collection.uri_type), - LinkedData::Hypermedia::Link.new("labels", lambda {|s| "artefacts/#{s.acronym}/labels"}, LinkedData::Models::SKOS::Label.uri_type) + link_to LinkedData::Hypermedia::Link.new("distributions", lambda {|s| "mod-api/artefacts/#{s.acronym}/distributions"}, LinkedData::Models::SemanticArtefactDistribution.type_uri), + LinkedData::Hypermedia::Link.new("record", lambda {|s| "mod-api/artefacts/#{s.acronym}/record"}, LinkedData::Models::SemanticArtefactCatalogRecord.type_uri), + LinkedData::Hypermedia::Link.new("resources", lambda {|s| "mod-api/artefacts/#{s.acronym}/resources"}), + LinkedData::Hypermedia::Link.new("classes", lambda {|s| "mod-api/artefacts/#{s.acronym}/resources/classes"}, LinkedData::Models::Class.uri_type), + LinkedData::Hypermedia::Link.new("concepts", lambda {|s| "mod-api/artefacts/#{s.acronym}/resources/concepts"}, LinkedData::Models::Class.uri_type), + LinkedData::Hypermedia::Link.new("properties", lambda {|s| "mod-api/artefacts/#{s.acronym}/resources/properties"}, "#{Goo.namespaces[:metadata].to_s}Property"), + LinkedData::Hypermedia::Link.new("individuals", lambda {|s| "mod-api/artefacts/#{s.acronym}/resources/individuals"}, LinkedData::Models::Class.uri_type), + LinkedData::Hypermedia::Link.new("schemes", lambda {|s| "mod-api/artefacts/#{s.acronym}/resources/schemes"}, LinkedData::Models::SKOS::Scheme.uri_type), + LinkedData::Hypermedia::Link.new("collection", lambda {|s| "mod-api/artefacts/#{s.acronym}/resources/collections"}, LinkedData::Models::SKOS::Collection.uri_type), + LinkedData::Hypermedia::Link.new("labels", lambda {|s| "mod-api/artefacts/#{s.acronym}/resources/labels"}, LinkedData::Models::SKOS::Label.uri_type) # Access control read_restriction_based_on ->(artefct) { artefct.ontology } @@ -167,7 +167,7 @@ def self.all_artefacts(attributes, page, pagesize) sa.bring(*attributes) if attributes end end - Goo::Base::Page.new(page, pagesize, all_count, all_artefacts) + LinkedData::Models::HydraPage.new(page, pagesize, all_count, all_artefacts) end def latest_distribution(status) @@ -180,15 +180,20 @@ def distribution(dist_id) SemanticArtefactDistribution.new(sub) unless sub.nil? end - def all_distributions(options = {}) - to_bring = options[:includes] - @ontology.bring(:submissions) - - @ontology.submissions.map do |submission| + def all_distributions(attributes, page, pagesize) + filter_by_acronym = Goo::Filter.new(ontology: [:acronym]) == @ontology.acronym + submissions_count = OntologySubmission.where.filter(filter_by_acronym).count + submissions_page = OntologySubmission.where.include(:distributionId) + .filter(filter_by_acronym) + .page(page, pagesize) + .page_count_set(submissions_count) + .all + all_distributions = submissions_page.map do |submission| SemanticArtefactDistribution.new(submission).tap do |dist| - dist.bring(*to_bring) if to_bring + dist.bring(*attributes) if attributes end end + LinkedData::Models::HydraPage.new(page, pagesize, submissions_count, all_distributions) end def analytics diff --git a/lib/ontologies_linked_data/models/mod/semantic_artefact_catalog.rb b/lib/ontologies_linked_data/models/mod/semantic_artefact_catalog.rb index a6331fca2..dbc63c71d 100644 --- a/lib/ontologies_linked_data/models/mod/semantic_artefact_catalog.rb +++ b/lib/ontologies_linked_data/models/mod/semantic_artefact_catalog.rb @@ -16,7 +16,7 @@ module LinkedData module Models - class SemanticArtefactCatalog < LinkedData::Models::Base + class SemanticArtefactCatalog < LinkedData::Models::ModBase model :SemanticArtefactCatalog, namespace: :mod, scheme: File.join(__dir__, '../../../../config/schemes/semantic_artefact_catalog.yml'), @@ -41,18 +41,18 @@ class SemanticArtefactCatalog < LinkedData::Models::Base attribute :relation, namespace: :dcterms, enforce: [:string] attribute :hasPolicy, namespace: :mod, enforce: [:string] attribute :themeTaxonomy, namespace: :mod, enforce: [:string] - + attribute :created, namespace: :dcterms, enforce: [:date] attribute :curatedOn, namespace: :pav, enforce: [:date] - + attribute :deprecated, namespace: :owl, enforce: [:boolean] - + attribute :homepage, namespace: :foaf, enforce: [:url], default: ->(s) { RDF::URI("http://#{LinkedData.settings.ui_host}") } attribute :logo, namespace: :foaf, enforce: [:url] attribute :license, namespace: :dcterms, enforce: [:url] attribute :mailingList, namespace: :mod, enforce: [:url] attribute :fairScore, namespace: :mod, enforce: [:url] - + attribute :federated_portals, enforce: [:list] attribute :fundedBy, namespace: :foaf, enforce: [:list] attribute :language, namespace: :dcterms, enforce: [:list] @@ -132,7 +132,7 @@ class SemanticArtefactCatalog < LinkedData::Models::Base numberOfMappings: :mappings_counts, numberOfAgents: :agents_counts } - + METRICS_ATTRIBUTES.each do |attr_name, config| handler = config.is_a?(Hash) ? config[:handler] : config mapped_to = config.is_a?(Hash) ? config[:mapped_to] : attr_name @@ -140,15 +140,12 @@ class SemanticArtefactCatalog < LinkedData::Models::Base define_method(handler) { calculate_attr_from_metrics(mapped_to) } end - link_to LinkedData::Hypermedia::Link.new("doc/legacy-api", lambda {|s| "documentation"}, nil), - LinkedData::Hypermedia::Link.new("doc/mod-api", lambda {|s| "doc/api"}, nil), + link_to LinkedData::Hypermedia::Link.new("documentation", lambda {|s| "documentation"}, nil), LinkedData::Hypermedia::Link.new("ontologies", lambda {|s| "ontologies"}, LinkedData::Models::Ontology.type_uri), LinkedData::Hypermedia::Link.new("ontologies_full", lambda {|s| "ontologies_full"}, LinkedData::Models::Ontology.type_uri), LinkedData::Hypermedia::Link.new("ontology_metadata", lambda {|s| "ontology_metadata"}, nil), LinkedData::Hypermedia::Link.new("submissions", lambda {|s| "submissions"}, LinkedData::Models::OntologySubmission.type_uri), LinkedData::Hypermedia::Link.new("submission_metadata", lambda {|s| "submission_metadata"}, nil), - LinkedData::Hypermedia::Link.new("artefacts", lambda {|s| "artefacts"}, LinkedData::Models::SemanticArtefact.type_uri), - LinkedData::Hypermedia::Link.new("records", lambda {|s| "records"}, nil), LinkedData::Hypermedia::Link.new("users", lambda {|s| "users"}, LinkedData::Models::User.type_uri), LinkedData::Hypermedia::Link.new("agents", lambda {|s| "agents"}, LinkedData::Models::Agent.type_uri), LinkedData::Hypermedia::Link.new("groups", lambda {|s| "groups"}, LinkedData::Models::Group.type_uri), @@ -166,16 +163,24 @@ class SemanticArtefactCatalog < LinkedData::Models::Base LinkedData::Hypermedia::Link.new("annotator", lambda {|s| "annotator"}, nil), LinkedData::Hypermedia::Link.new("notes", lambda {|s| "notes"}, LinkedData::Models::Note.type_uri), LinkedData::Hypermedia::Link.new("replies", lambda {|s| "replies"}, LinkedData::Models::Notes::Reply.type_uri), - LinkedData::Hypermedia::Link.new("reviews", lambda {|s| "reviews"}, LinkedData::Models::Review.type_uri) - - serialize_default :acronym, :title, :identifier, :status, :language, :type, :accessRights, :license, :rightsHolder, :description, - :landingPage, :keyword, :bibliographicCitation, :created, :modified , :contactPoint, :creator, :contributor, - :publisher, :subject, :coverage, :createdWith, :accrualMethod, :accrualPeriodicity, :wasGeneratedBy, :accessURL + LinkedData::Hypermedia::Link.new("reviews", lambda {|s| "reviews"}, LinkedData::Models::Review.type_uri), + LinkedData::Hypermedia::Link.new("mod-api_documentation", lambda {|s| "mod-api/doc"}, nil), + LinkedData::Hypermedia::Link.new("artefacts", lambda {|s| "mod-api/artefacts"}, LinkedData::Models::SemanticArtefact.type_uri), + LinkedData::Hypermedia::Link.new("records", lambda {|s| "mod-api/records"}, LinkedData::Models::SemanticArtefactCatalogRecord.type_uri), + LinkedData::Hypermedia::Link.new("search_content", lambda {|s| "mod-api/search/content"}, nil), + LinkedData::Hypermedia::Link.new("search_metadata", lambda {|s| "mod-api/search/metadata"}, nil) + + serialize_default :acronym, :title, :color, :description, :logo,:identifier, :status, :language, :type, :accessRights, :license, :rightsHolder, + :landingPage, :keyword, :bibliographicCitation, :created, :modified , :contactPoint, :creator, :contributor, + :publisher, :subject, :coverage, :createdWith, :accrualMethod, :accrualPeriodicity, :wasGeneratedBy, :accessURL, + :numberOfArtefacts, :federated_portals, :fundedBy + + embed :rightsHolder, :contactPoint, :creator, :contributor, :curatedBy, :translator, :publisher, :endorsedBy def self.type_uri namespace[model_name].to_s end - + def ontologies_count LinkedData::Models::Ontology.where(viewingRestriction: 'public').count end @@ -203,11 +208,11 @@ def set_uri_regex_pattern def set_preferred_namespace_uri "" end - + def set_preferred_namespace_prefix "" end - + def set_metadata_voc "" end @@ -215,11 +220,11 @@ def set_metadata_voc def mod_uri RDF::URI("https://w3id.org/mod") end - + def set_feature_list [] end - + def set_supported_schema [] end diff --git a/lib/ontologies_linked_data/models/mod/semantic_artefact_catalog_record.rb b/lib/ontologies_linked_data/models/mod/semantic_artefact_catalog_record.rb new file mode 100644 index 000000000..e4128f64b --- /dev/null +++ b/lib/ontologies_linked_data/models/mod/semantic_artefact_catalog_record.rb @@ -0,0 +1,97 @@ +module LinkedData + module Models + class SemanticArtefactCatalogRecord < LinkedData::Models::ModBase + include LinkedData::Concerns::SemanticArtefact::AttributeMapping + include LinkedData::Concerns::SemanticArtefact::AttributeFetcher + + model :SemanticArtefactCatalogRecord, namespace: :mod, name_with: ->(r) { record_id_generator(r) } + + # mod specs attributes + attribute_mapped :acronym, namespace: :omv, mapped_to: { model: :ontology } + attribute_mapped :relatedArtefactId, mapped_to: { model: self }, default: ->(r) { RDF::URI("#{(Goo.id_prefix)}artefacts/#{CGI.escape(r.ontology.acronym.to_s)}") } + attribute_mapped :homepage, namespace: :foaf, mapped_to: { model: self }, default: ->(r) { RDF::URI("http://#{LinkedData.settings.ui_host}/#{r.ontology.acronym}") } #handler: :record_home_page + attribute_mapped :created, namespace: :dcterms, mapped_to: { model: self }, handler: :get_creation_date + attribute_mapped :modified, namespace: :dcterms, mapped_to: { model: self }, handler: :get_modification_date + attribute_mapped :curatedOn, namespace: :pav, mapped_to: { model: :ontology_submission } + attribute_mapped :curatedBy, namespace: :pav, mapped_to: { model: :ontology_submission } + + # additional attributes + attribute_mapped :viewingRestriction, mapped_to: { model: :ontology } + attribute_mapped :administeredBy, mapped_to: { model: :ontology } + attribute_mapped :doNotUpdate, mapped_to: { model: :ontology } + attribute_mapped :flat, mapped_to: { model: :ontology } + attribute_mapped :summaryOnly, mapped_to: { model: :ontology } + attribute_mapped :acl, mapped_to: { model: :ontology } + attribute_mapped :ontologyType, mapped_to: { model: :ontology } + attribute_mapped :classType, mapped_to: { model: :ontology_submission } + attribute_mapped :missingImports, mapped_to: { model: :ontology_submission } + attribute_mapped :submissionStatus, mapped_to: { model: :ontology_submission } + attribute_mapped :pullLocation, mapped_to: { model: :ontology_submission } + attribute_mapped :dataDump, namespace: :void, mapped_to: { model: :ontology_submission } + attribute_mapped :csvDump, mapped_to: { model: :ontology_submission } + attribute_mapped :uploadFilePath, mapped_to: { model: :ontology_submission } + attribute_mapped :diffFilePath, mapped_to: { model: :ontology_submission } + attribute_mapped :masterFileName, mapped_to: { model: :ontology_submission } + + + attribute :ontology, type: :ontology, enforce: [:existence] + attribute :submission, type: :ontology_submission + + # Access control + read_restriction_based_on ->(record) { record.ontology } + + serialize_default :acronym, :relatedArtefactId, :homepage, :created, :modified, :curatedOn, :curatedBy + serialize_never :ontology, :submission + + def self.record_id_generator(record) + record.ontology.bring(:acronym) if record.ontology.bring?(:acronym) + raise ArgumentError, "Acronym is nil for ontology #{record.ontology.id} to generate id" if record.ontology.acronym.nil? + return RDF::URI.new( + "#{(Goo.id_prefix)}records/#{CGI.escape(record.ontology.acronym.to_s)}" + ) + end + + ## + ## find an artefact (ontology) and map it to record + def self.find(artefact_id) + ont = Ontology.find(artefact_id).include(:acronym, :viewingRestriction, :administeredBy, :acl).first + return nil unless ont + new.tap do |sacr| + sacr.ontology = ont + end + end + + def self.all(attributes, page, pagesize) + all_count = Ontology.where.count + onts = Ontology.where.include(:acronym, :viewingRestriction, :administeredBy, :acl).page(page, pagesize).page_count_set(all_count).all + all_records = onts.map do |o| + new.tap do |sacr| + sacr.ontology = o + sacr.bring(*attributes) if attributes + end + end + LinkedData::Models::HydraPage.new(page, pagesize, all_count, all_records) + end + + private + def get_modification_date + fetch_submission_date(:max_by) + end + + def get_creation_date + fetch_submission_date(:min_by) + end + + def fetch_submission_date(method) + @ontology.bring(submissions: [:submissionId, :creationDate]) if @ontology.bring?(:submissions) + submission = @ontology.submissions.public_send(method, &:submissionId) + return unless submission + + submission.bring(:creationDate) unless submission.bring?(:creationDate) + submission.creationDate + end + + + end + end +end diff --git a/lib/ontologies_linked_data/models/mod/semantic_artefact_distribution.rb b/lib/ontologies_linked_data/models/mod/semantic_artefact_distribution.rb index 21ad32993..019aad3bd 100644 --- a/lib/ontologies_linked_data/models/mod/semantic_artefact_distribution.rb +++ b/lib/ontologies_linked_data/models/mod/semantic_artefact_distribution.rb @@ -1,7 +1,7 @@ module LinkedData module Models - class SemanticArtefactDistribution < LinkedData::Models::Base + class SemanticArtefactDistribution < LinkedData::Models::ModBase include LinkedData::Concerns::SemanticArtefact::AttributeMapping include LinkedData::Concerns::SemanticArtefact::AttributeFetcher @@ -9,7 +9,7 @@ class SemanticArtefactDistribution < LinkedData::Models::Base # SAD attrs that map with submission attribute_mapped :distributionId, mapped_to: { model: :ontology_submission, attribute: :submissionId } - attribute_mapped :title, namespace: :dcterms, mapped_to: { model: :ontology_submission, attribute: :URI } + attribute_mapped :title, namespace: :dcterms, mapped_to: { model: :ontology, attribute: :name } attribute_mapped :deprecated, namespace: :owl, mapped_to: { model: :ontology_submission } attribute_mapped :hasRepresentationLanguage, namespace: :mod, mapped_to: { model: :ontology_submission, attribute: :hasOntologyLanguage } attribute_mapped :hasFormalityLevel, namespace: :mod, mapped_to: { model: :ontology_submission } @@ -60,8 +60,10 @@ class SemanticArtefactDistribution < LinkedData::Models::Base attribute_mapped :classesWithNoAuthorMetadata, namespace: :mod, enforce: [:integer], mapped_to: { model: :metric } attribute_mapped :classesWithNoDateMetadata, namespace: :mod, enforce: [:integer], mapped_to: { model: :metric } attribute_mapped :numberOfMappings, namespace: :mod, enforce: [:integer], mapped_to: { model: :metric } + attribute_mapped :byteSize, namespace: :dcat, mapped_to: { model: self }, handler: :calculate_byte_size # Attr special to SemanticArtefactDistribution + attribute :ontology, type: :ontology attribute :submission, type: :ontology_submission # Access control @@ -69,7 +71,7 @@ class SemanticArtefactDistribution < LinkedData::Models::Base serialize_default :distributionId, :title, :hasRepresentationLanguage, :hasSyntax, :description, :created, :modified, :conformsToKnowledgeRepresentationParadigm, :usedEngineeringMethodology, :prefLabelProperty, - :synonymProperty, :definitionProperty, :accessURL, :downloadURL + :synonymProperty, :definitionProperty, :accessURL, :downloadURL, :byteSize serialize_never :submission @@ -78,7 +80,7 @@ def self.distribution_id_generator(ss) ss.submission.ontology.bring(:acronym) if !ss.submission.ontology.loaded_attributes.include?(:acronym) raise ArgumentError, "Acronym is nil to generate id" if ss.submission.ontology.acronym.nil? return RDF::URI.new( - "#{(Goo.id_prefix)}artefacts/#{CGI.escape(ss.submission.ontology.acronym.to_s)}/distributions/#{ss.submission.submissionId.to_s}" + "#{(Goo.id_prefix)}artefacts/#{CGI.escape(ss.ontology.acronym.to_s)}/distributions/#{ss.submission.submissionId.to_s}" ) end @@ -88,6 +90,13 @@ def initialize(sub) @submission = sub @submission.bring(*[:submissionId, :ontology=>[:acronym, :administeredBy, :acl, :viewingRestriction]]) @distributionId = sub.submissionId + @ontology = @submission.ontology + end + + def calculate_byte_size + @submission.bring(:uploadFilePath) if @submission.bring?(:uploadFilePath) + upload_file_path = @submission.uploadFilePath + File.exist?(upload_file_path.to_s) ? File.size(upload_file_path.to_s) : 0 end diff --git a/lib/ontologies_linked_data/models/portal_config.rb b/lib/ontologies_linked_data/models/portal_config.rb deleted file mode 100644 index 18169fca4..000000000 --- a/lib/ontologies_linked_data/models/portal_config.rb +++ /dev/null @@ -1,57 +0,0 @@ -module LinkedData - module Models - class PortalConfig < LinkedData::Models::Base - model :SemanticArtefactCatalogue, namespace: :mod, name_with: :acronym - attribute :acronym, enforce: [:unique, :existence] - attribute :title, namespace: :dcterms, enforce: [:existence] - attribute :color, enforce: [:existence, :valid_hash_code] - attribute :description, namespace: :dcterms - attribute :logo, namespace: :foaf, enforce: [:url] - attribute :numberOfArtefacts, namespace: :mod, handler: :ontologies_count - attribute :federated_portals, handler: :federated_portals_settings - attribute :fundedBy, namespace: :foaf, enforce: [:list] - - serialize_default :acronym, :title, :color, :description, :logo, :numberOfArtefacts, :federated_portals, :fundedBy - - def initialize(*args) - super - init_federated_portals_settings - end - - def self.current_portal_config - p = LinkedData::Models::PortalConfig.new - - p.acronym = LinkedData.settings.ui_name.downcase - p.title = LinkedData.settings.title - p.description = LinkedData.settings.description - p.color = LinkedData.settings.color - p.logo = LinkedData.settings.logo - p.fundedBy = LinkedData.settings.fundedBy - p - end - - def init_federated_portals_settings(federated_portals = nil) - @federated_portals = federated_portals || LinkedData.settings.federated_portals.symbolize_keys - end - - def federated_portals_settings - @federated_portals - end - - def ontologies_count - LinkedData::Models::Ontology.where(viewingRestriction: 'public').count - end - - def self.valid_hash_code(inst, attr) - inst.bring(attr) if inst.bring?(attr) - str = inst.send(attr) - - return if (/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/ === str) - [:valid_hash_code, - "Invalid hex color code: '#{str}'. Please provide a valid hex code in the format '#FFF' or '#FFFFFF'."] - end - end - end -end - - diff --git a/lib/ontologies_linked_data/monkeypatches/object.rb b/lib/ontologies_linked_data/monkeypatches/object.rb index 45599d1b3..38fa5cff9 100644 --- a/lib/ontologies_linked_data/monkeypatches/object.rb +++ b/lib/ontologies_linked_data/monkeypatches/object.rb @@ -190,6 +190,8 @@ def enumerable_handling(options, &block) new_hash[key] = value.to_flex_hash(options, &block) end return new_hash + elsif kind_of?(LinkedData::Models::HydraPage) + return self.convert_hydra_page(options, &block) elsif kind_of?(Goo::Base::Page) return convert_goo_page(options, &block) end diff --git a/lib/ontologies_linked_data/serializers/json.rb b/lib/ontologies_linked_data/serializers/json.rb index e4161b49c..187b460d7 100644 --- a/lib/ontologies_linked_data/serializers/json.rb +++ b/lib/ontologies_linked_data/serializers/json.rb @@ -7,48 +7,86 @@ class JSON def self.serialize(obj, options = {}) + return serialize_mod_objects(obj, options) if mod_object?(obj) + # Handle the serialization for all other objects in the standard way hash = obj.to_flex_hash(options) do |hash, hashed_obj| - current_cls = hashed_obj.respond_to?(:klass) ? hashed_obj.klass : hashed_obj.class - result_lang = self.get_languages(get_object_submission(hashed_obj), options[:lang]) if result_lang.nil? + process_common_serialization(hash, hashed_obj, options) + end + MultiJson.dump(hash) + end + + def self.serialize_mod_objects(obj, options = {}) + # using one context and links in mod objects + global_context = {} - # Add the id to json-ld attribute - if current_cls.ancestors.include?(LinkedData::Hypermedia::Resource) && !current_cls.embedded? && hashed_obj.respond_to?(:id) - prefixed_id = LinkedData::Models::Base.replace_url_id_to_prefix(hashed_obj.id) - hash["@id"] = prefixed_id.to_s - end + hash = obj.to_flex_hash(options) do |hash, hashed_obj| + process_common_serialization(hash, hashed_obj, options, global_context) + end - # Add the type - hash["@type"] = type(current_cls, hashed_obj) if hash["@id"] - - # Generate links - # NOTE: If this logic changes, also change in xml.rb - if generate_links?(options) - links = LinkedData::Hypermedia.generate_links(hashed_obj) - unless links.empty? - hash["links"] = links - hash["links"].merge!(generate_links_context(hashed_obj)) if generate_context?(options) - end - end + result = {} + # handle adding the context for HydraPage + if obj.is_a?(LinkedData::Models::HydraPage) + global_context["@context"] ||= {} + global_context["@context"].merge!(LinkedData::Models::HydraPage.generate_hydra_context) + end + result.merge!(global_context) unless global_context.empty? + result.merge!(hash) if hash.is_a?(Hash) + MultiJson.dump(result) + end + + + private + + def self.process_common_serialization(hash, hashed_obj, options, global_context= nil) + current_cls = hashed_obj.respond_to?(:klass) ? hashed_obj.klass : hashed_obj.class + result_lang = get_languages(get_object_submission(hashed_obj), options[:lang]) + + add_id_and_type(hash, hashed_obj, current_cls) + add_links(hash, hashed_obj, options) if generate_links?(options) + add_context(hash, hashed_obj, options, current_cls, result_lang, global_context) if generate_context?(options) + end - # Generate context + def self.add_id_and_type(hash, hashed_obj, current_cls) + return unless current_cls.ancestors.include?(LinkedData::Hypermedia::Resource) && !current_cls.embedded? && hashed_obj.respond_to?(:id) + + hash["@id"] = LinkedData::Models::Base.replace_url_id_to_prefix(hashed_obj.id).to_s + hash["@type"] = type(current_cls, hashed_obj) if hash["@id"] + end + + def self.add_links(hash, hashed_obj, options) + links = LinkedData::Hypermedia.generate_links(hashed_obj) + return if links.empty? + hash["links"] = links + hash["links"].merge!(generate_links_context(hashed_obj)) if generate_context?(options) + end + + def self.add_context(hash, hashed_obj, options, current_cls, result_lang, global_context) + return if global_context&.any? + + if global_context.nil? if current_cls.ancestors.include?(Goo::Base::Resource) && !current_cls.embedded? - if generate_context?(options) - context = generate_context(hashed_obj, hash.keys, options) - hash.merge!(context) - end + context = generate_context(hashed_obj, hash.keys, options) + hash.merge!(context) elsif (hashed_obj.instance_of?(LinkedData::Models::ExternalClass) || hashed_obj.instance_of?(LinkedData::Models::InterportalClass)) && !current_cls.embedded? # Add context for ExternalClass - context_hash = { "@vocab" => Goo.vocabulary.to_s, "prefLabel" => "http://data.bioontology.org/metadata/skosprefLabel" } - context = { "@context" => context_hash } - hash.merge!(context) + external_class_context = { "@context" => { "@vocab" => Goo.vocabulary.to_s, "prefLabel" => "http://data.bioontology.org/metadata/skosprefLabel" } } + hash.merge!(external_class_context) end hash['@context']['@language'] = result_lang if hash['@context'] + elsif global_context.empty? + context = generate_context(hashed_obj, hash.keys, options) + global_context.replace(context) + global_context["@context"]["@language"] = result_lang unless global_context.empty? end - MultiJson.dump(hash) end - private + def self.mod_object?(obj) + return false if obj.nil? + single_object = (obj.class == Array) && obj.any? ? obj.first : obj + single_object.class.ancestors.include?(LinkedData::Models::HydraPage) || single_object.class.ancestors.include?(LinkedData::Models::ModBase) + end + def self.get_object_submission(obj) obj.class.respond_to?(:attributes) && obj.class.attributes.include?(:submission) ? obj.submission : nil diff --git a/test/models/mod/test_artefact.rb b/test/models/mod/test_artefact.rb index ecabe518a..620261b57 100644 --- a/test/models/mod/test_artefact.rb +++ b/test/models/mod/test_artefact.rb @@ -3,13 +3,18 @@ class TestArtefact < LinkedData::TestOntologyCommon + def self.before_suite + backend_4s_delete + helper = LinkedData::TestOntologyCommon.new(self) + helper.init_test_ontology_msotest "STY" + end + def test_create_artefact sa = LinkedData::Models::SemanticArtefact.new assert_equal LinkedData::Models::SemanticArtefact , sa.class end def test_find_artefact - create_test_ontology sa = LinkedData::Models::SemanticArtefact.find('STY') assert_equal LinkedData::Models::SemanticArtefact , sa.class assert_equal "STY", sa.acronym @@ -25,7 +30,6 @@ def test_goo_attrs_to_load end def test_bring_attrs - create_test_ontology r = LinkedData::Models::SemanticArtefact.find('STY') r.bring(*LinkedData::Models::SemanticArtefact.goo_attrs_to_load([:all])) ont = r.ontology @@ -77,7 +81,6 @@ def test_bring_attrs def test_latest_distribution - create_test_ontology sa = LinkedData::Models::SemanticArtefact.find('STY') assert_equal "STY", sa.acronym latest_distribution = sa.latest_distribution(status: :any) @@ -87,25 +90,25 @@ def test_latest_distribution assert_equal 1, latest_distribution.submission.submissionId end + def test_all_artefacts + attributes = LinkedData::Models::SemanticArtefact.goo_attrs_to_load([]) + page = 1 + pagesize = 1 + all_artefacts = LinkedData::Models::SemanticArtefact.all_artefacts(attributes, page, pagesize) + assert_equal LinkedData::Models::HydraPage, all_artefacts.class + assert_equal 1, all_artefacts.length + assert_equal LinkedData::Models::SemanticArtefact, all_artefacts[0].class + end + def test_distributions - create_test_ontology r = LinkedData::Models::SemanticArtefact.find('STY') - options = { - status: "ANY", - includes: LinkedData::Models::SemanticArtefactDistribution.goo_attrs_to_load([]) - } - all_distros = r.all_distributions(options) - - assert_equal Array, all_distros.class - assert_equal 1, all_distros.length + attributes = LinkedData::Models::SemanticArtefactDistribution.goo_attrs_to_load([]) + page = 1 + pagesize = 1 + all_distros = r.all_distributions(attributes, page, pagesize) + assert_equal LinkedData::Models::HydraPage, all_distros.class assert_equal 1, all_distros.length assert_equal LinkedData::Models::SemanticArtefactDistribution, all_distros[0].class - assert_equal Set[:distributionId, :title, :hasRepresentationLanguage, :hasSyntax, :description, :created, :modified, :conformsToKnowledgeRepresentationParadigm, :usedEngineeringMethodology, :prefLabelProperty, :synonymProperty, :definitionProperty, :accessURL, :downloadURL], all_distros[0].loaded_attributes - end - - private - def create_test_ontology - acr = "STY" - init_test_ontology_msotest acr end + end \ No newline at end of file diff --git a/test/models/mod/test_artefact_catalog.rb b/test/models/mod/test_artefact_catalog.rb index a6c46c053..c4d599286 100644 --- a/test/models/mod/test_artefact_catalog.rb +++ b/test/models/mod/test_artefact_catalog.rb @@ -3,17 +3,60 @@ class TestArtefactCatalog < LinkedData::TestOntologyCommon + def self.before_suite + backend_4s_delete + self.new("before_suite").teardown + catalog = LinkedData::Models::SemanticArtefactCatalog.new + catalog.save + end + + def self.after_suite + self.new("before_suite").teardown + end + def test_create_artefact_catalog - sac = LinkedData::Models::SemanticArtefactCatalog.new - assert_equal LinkedData::Models::SemanticArtefactCatalog , sac.class - assert_equal "http://data.bioontology.org/", sac.id.to_s + catalog = LinkedData::Models::SemanticArtefactCatalog.all.first + assert_equal LinkedData::Models::SemanticArtefactCatalog , catalog.class + catalog.bring(*LinkedData::Models::SemanticArtefactCatalog.goo_attrs_to_load([])) + expected = { + acronym: "OntoPortal", + title: "OntoPortal", + color: "#5499A3", + description: "Welcome to OntoPortal Appliance, your ontology repository for your ontologies", + status: "alpha", + accessRights: "public", + logo: "https://ontoportal.org/images/logo.png", + license: "https://opensource.org/licenses/BSD-2-Clause", + federated_portals: [ + "{:name=>\"agroportal\", :api=>\"http://data.agroportal.lirmm.fr\", :ui=>\"http://agroportal.lirmm.fr\", :apikey=>\"DUMMY_API_KEY_123456\", :color=>\"#3cb371\"}" + ], + fundedBy: [ + "{:img_src=>\"https://ontoportal.org/images/logo.png\", :url=>\"https://ontoportal.org/\"}" + ], + language: ["English"], + keyword: [], + bibliographicCitation: [], + subject: [], + coverage: [], + createdWith: [], + accrualMethod: [], + accrualPeriodicity: [], + wasGeneratedBy: [], + contactPoint: [], + creator: [], + contributor: [], + publisher: [], + id: RDF::URI("http://data.bioontology.org/") + } + assert_equal expected, catalog.to_hash + refute_nil catalog.numberOfArtefacts end def test_goo_attrs_to_load default_attrs = LinkedData::Models::SemanticArtefactCatalog.goo_attrs_to_load([]) - assert_equal [:acronym, :title, :identifier, :status, :language, :type, :accessRights, :license, :rightsHolder, - :description, :landingPage, :keyword, :bibliographicCitation, :created, :modified, :contactPoint, :creator, - :contributor, :publisher, :subject, :coverage, :createdWith, :accrualMethod, :accrualPeriodicity, :wasGeneratedBy, :accessURL], default_attrs + assert_equal [:acronym, :title, :color, :description, :logo, :identifier, :status, :language, :type, :accessRights, :license, :rightsHolder, + :landingPage, :keyword, :bibliographicCitation, :created, :modified, :contactPoint, :creator, :contributor, :publisher, :subject, + :coverage, :createdWith, :accrualMethod, :accrualPeriodicity, :wasGeneratedBy, :accessURL, :numberOfArtefacts, :federated_portals, :fundedBy].sort, (default_attrs.flat_map { |e| e.is_a?(Hash) ? e.keys : e }).sort specified_attrs = LinkedData::Models::SemanticArtefactCatalog.goo_attrs_to_load([:acronym, :title, :keyword, :featureList]) assert_equal [:acronym, :title, :keyword, :featureList], specified_attrs @@ -25,12 +68,10 @@ def test_goo_attrs_to_load assert_equal computed_attrs, computed_attrs_bring end - def test_bring_attrs - sac = LinkedData::Models::SemanticArtefactCatalog.new - assert_equal true, sac.valid? - sac.save + def test_bring_all_attrs + sac = LinkedData::Models::SemanticArtefactCatalog.all.first all_attrs_to_bring = LinkedData::Models::SemanticArtefactCatalog.goo_attrs_to_load([:all]) sac.bring(*all_attrs_to_bring) - assert_equal all_attrs_to_bring.sort, (sac.loaded_attributes.to_a + [:type]).sort + assert_equal (all_attrs_to_bring.flat_map { |e| e.is_a?(Hash) ? e.keys : e }).sort, (sac.loaded_attributes.to_a + [:type]).sort end end \ No newline at end of file diff --git a/test/models/mod/test_artefact_distribution.rb b/test/models/mod/test_artefact_distribution.rb index e99b26d3c..48ad9f9d8 100644 --- a/test/models/mod/test_artefact_distribution.rb +++ b/test/models/mod/test_artefact_distribution.rb @@ -16,7 +16,7 @@ def test_goo_attrs_to_load attrs = LinkedData::Models::SemanticArtefactDistribution.goo_attrs_to_load([]) assert_equal [:distributionId, :title, :hasRepresentationLanguage, :hasSyntax, :description, :created, :modified, :conformsToKnowledgeRepresentationParadigm, :usedEngineeringMethodology, :prefLabelProperty, - :synonymProperty, :definitionProperty, :accessURL, :downloadURL], attrs + :synonymProperty, :definitionProperty, :accessURL, :downloadURL, :byteSize], attrs end def test_bring_attrs diff --git a/test/models/test_portal_configuration.rb b/test/models/test_portal_configuration.rb deleted file mode 100644 index dcebbc936..000000000 --- a/test/models/test_portal_configuration.rb +++ /dev/null @@ -1,27 +0,0 @@ -require_relative '../test_case' - -class TestPortalConfiguration < LinkedData::TestCase - - def test_read_portal_config - config = LinkedData::Models::PortalConfig.current_portal_config - - expected = { acronym: 'bioportal', - title: 'NCBO BioPortal', - color: '#234979', - description: "The world's most comprehensive repository of biomedical ontologies", - logo: '', - fundedBy: [{ img_src: 'https://identity.stanford.edu/wp-content/uploads/sites/3/2020/07/block-s-right.png', url: 'https://www.stanford.edu' }, - { img_src: 'https://ontoportal.org/images/logo.png', url: 'https://ontoportal.org/' }], - id: RDF::URI.new('http://data.bioontology.org/SemanticArtefactCatalogues/bioportal') } - - assert config.valid? - - assert_equal expected, config.to_hash - - expected_federated_portals = { 'agroportal' => { api: 'http://data.agroportal.lirmm.fr', ui: 'http://agroportal.lirmm.fr', apikey: '1cfae05f-9e67-486f-820b-b393dec5764b', color: '#1e2251' }, - 'bioportal' => { api: 'http://data.bioontology.org', ui: 'http://bioportal.bioontology.org', apikey: '4a5011ea-75fa-4be6-8e89-f45c8c84844e', color: '#234979' } }.symbolize_keys - assert_equal expected_federated_portals, config.federated_portals - refute_nil config.numberOfArtefacts - end -end -