Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ interaction:

test-ag:
description: Run minitest unit tests
service: ruby-ag
service: ruby-agraph
command: bundle exec rake test


Expand Down
2 changes: 1 addition & 1 deletion lib/ontologies_linked_data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
end

# We need to require deterministic - that is why we have the sort.
models = Dir.glob("#{project_root}/ontologies_linked_data/models/concerns//**/*.rb").sort
models = Dir.glob("#{project_root}/ontologies_linked_data/models/concerns/**/*.rb").sort
models.each do |m|
require m
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module LinkedData
module Concerns
module Concept
module InCollection
def self.included(base)
base.serialize_methods :isInActiveCollection
end

def isInActiveCollection
@isInActiveCollection
end

def inCollection?(collection)
self.memberOf.include?(collection)
end

def load_is_in_collection(collections = [])
included = collections.select { |s| inCollection?(s) }
@isInActiveCollection = included
end

end
end
end
end
26 changes: 26 additions & 0 deletions lib/ontologies_linked_data/concerns/concepts/concept_in_scheme.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module LinkedData
module Concerns
module Concept
module InScheme
def self.included(base)
base.serialize_methods :isInActiveScheme
end

def isInActiveScheme
@isInActiveScheme
end

def inScheme?(scheme)
self.inScheme.include?(scheme)
end

def load_is_in_scheme(schemes = [])
included = schemes.select { |s| inScheme?(s) }
included = [self.submission.get_main_concept_scheme] if included.empty? && schemes&.empty?
@isInActiveScheme = included
end

end
end
end
end
55 changes: 55 additions & 0 deletions lib/ontologies_linked_data/concerns/concepts/concept_sort.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
module LinkedData
module Concerns
module Concept
module Sort
module ClassMethods
def compare_classes(class_a, class_b)
label_a = ""
label_b = ""
class_a.bring(:prefLabel) if class_a.bring?(:prefLabel)
class_b.bring(:prefLabel) if class_b.bring?(:prefLabel)

begin
label_a = class_a.prefLabel unless (class_a.prefLabel.nil? || class_a.prefLabel.empty?)
rescue Goo::Base::AttributeNotLoaded
label_a = ""
end

begin
label_b = class_b.prefLabel unless (class_b.prefLabel.nil? || class_b.prefLabel.empty?)
rescue Goo::Base::AttributeNotLoaded
label_b = ""
end

label_a = class_a.id if label_a.empty?
label_b = class_b.id if label_b.empty?

[label_a.downcase] <=> [label_b.downcase]
end

def sort_classes(classes)
classes.sort { |class_a, class_b| compare_classes(class_a, class_b) }
end

def sort_tree_children(root_node)
sort_classes!(root_node.children)
root_node.children.each { |ch| sort_tree_children(ch) }
end

private



def sort_classes!(classes)
classes.sort! { |class_a, class_b| LinkedData::Models::Class.compare_classes(class_a, class_b) }
classes
end
end

def self.included(base)
base.extend(ClassMethods)
end
end
end
end
end
139 changes: 139 additions & 0 deletions lib/ontologies_linked_data/concerns/concepts/concept_tree.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
module LinkedData
module Concerns
module Concept
module Tree
def tree(concept_schemes: [], concept_collections: [], roots: nil)
bring(parents: [:prefLabel]) if bring?(:parents)
return self if parents.nil? || parents.empty?
extra_include = [:hasChildren, :isInActiveScheme, :isInActiveCollection]
roots = self.submission.roots( extra_include, concept_schemes:concept_schemes) if roots.nil?
path = path_to_root(roots)
threshold = 99

return self if path.nil?

attrs_to_load = %i[prefLabel synonym obsolete]
attrs_to_load << :subClassOf if submission.hasOntologyLanguage.obo?
attrs_to_load += self.class.concept_is_in_attributes if submission.skos?
self.class.in(submission)
.models(path)
.include(attrs_to_load).all
load_children(path, threshold: threshold)

path.reverse!
path.last.instance_variable_set("@children", [])

childrens_hash = {}
path.each do |m|
next if m.id.to_s["#Thing"]
m.children.each do |c|
childrens_hash[c.id.to_s] = c
c.load_computed_attributes(to_load:extra_include ,
options: {schemes: concept_schemes, collections: concept_collections})
end
m.load_computed_attributes(to_load:extra_include ,
options: {schemes: concept_schemes, collections: concept_collections})
end

load_children(childrens_hash.values, threshold: threshold)

build_tree(path)
end

def tree_sorted(concept_schemes: [], concept_collections: [], roots: nil)
tr = tree(concept_schemes: concept_schemes, concept_collections: concept_collections, roots: roots)
self.class.sort_tree_children(tr)
tr
end

def paths_to_root(tree: false, roots: nil)
bring(parents: [:prefLabel, :synonym, :definition]) if bring?(:parents)
return [] if parents.nil? || parents.empty?

paths = [[self]]
traverse_path_to_root(self.parents.dup, paths, 0, tree, roots) unless tree_root?(self, roots)
paths.each do |p|
p.reverse!
end
paths
end

def path_to_root(roots)
paths = [[self]]
paths = paths_to_root(tree: true, roots: roots)
#select one path that gets to root
path = nil
paths.each do |p|
p.reverse!
unless (p.map { |x| x.id.to_s } & roots.map { |x| x.id.to_s }).empty?
path = p
break
end
end

if path.nil?
# do one more check for root classes that don't get returned by the submission.roots call
paths.each do |p|
root_node = p.last
root_parents = root_node.parents

if root_parents.empty?
path = p
break
end
end
end

path
end

def tree_root?(concept, roots)
(roots &&roots.map{|r| r.id}.include?(concept.id)) || concept.id.to_s["#Thing"]
end

private

def load_children(concepts, threshold: 99)
LinkedData::Models::Class
.partially_load_children(concepts, threshold, submission)
end

def build_tree(path)
root_node = path.first
tree_node = path.first
path.delete_at(0)
while tree_node &&
!tree_node.id.to_s["#Thing"] &&
!tree_node.children.empty? && (!path.empty?) do
next_tree_node = nil
tree_node.load_has_children
tree_node.children.each_index do |i|
if tree_node.children[i].id.to_s == path.first.id.to_s
next_tree_node = path.first
children = tree_node.children.dup
children[i] = path.first
tree_node.instance_variable_set("@children", children)
children.each do |c|
c.load_has_children
end
else
tree_node.children[i].instance_variable_set("@children", [])
end
end

if !path.empty? && next_tree_node.nil?
tree_node.children << path.shift
end
tree_node = next_tree_node
path.delete_at(0)
end

root_node
end

end
end

end
end

Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
module LinkedData
module Models
module SKOS
module RootsFetcher

def skos_roots(concept_schemes, page, paged, pagesize)
classes = []
class_ids, count = roots_by_has_top_concept(concept_schemes, page, paged, pagesize)

class_ids, count = roots_by_top_concept_of(concept_schemes, page, paged, pagesize) if class_ids.empty?

class_ids.each do |id|
classes << LinkedData::Models::Class.find(id).in(self).disable_rules.first
end

classes = Goo::Base::Page.new(page, pagesize, count, classes) if paged
classes
end

private

def roots_by_query(query_body, page, paged, pagesize)
root_skos = <<-eos
SELECT DISTINCT ?root WHERE {
GRAPH #{self.id.to_ntriples} {
#{query_body}
}}
eos
count = 0

count, root_skos = add_pagination(query_body, page, pagesize, root_skos) if paged

#needs to get cached
class_ids = []

Goo.sparql_query_client.query(root_skos, { graphs: [self.id] }).each_solution do |s|
class_ids << s[:root]
end

[class_ids, count]
end

def roots_by_has_top_concept(concept_schemes, page, paged, pagesize)
query_body = <<-eos
?x #{RDF::SKOS[:hasTopConcept].to_ntriples} ?root .
#{concept_schemes_filter(concept_schemes)}
eos
roots_by_query query_body, page, paged, pagesize
end

def roots_by_top_concept_of(concept_schemes, page, paged, pagesize)
query_body = <<-eos
?root #{RDF::SKOS[:topConceptOf].to_ntriples} ?x.
#{concept_schemes_filter(concept_schemes)}
eos
roots_by_query query_body, page, paged, pagesize
end

def add_pagination(query_body, page, pagesize, root_skos)
count = count_roots(query_body)

offset = (page - 1) * pagesize
root_skos = "#{root_skos} LIMIT #{pagesize} OFFSET #{offset}"
[count, root_skos]
end

def count_roots(query_body)
query = <<-eos
SELECT (COUNT(?x) as ?count) WHERE {
GRAPH #{self.id.to_ntriples} {
#{query_body}
}}
eos
rs = Goo.sparql_query_client.query(query)
count = 0
rs.each do |sol|
count = sol[:count].object
end
count
end

def concept_schemes_filter(concept_schemes)
concept_schemes = current_schemes(concept_schemes)
concept_schemes = concept_schemes.map { |x| RDF::URI.new(x.to_s).to_ntriples }
concept_schemes.empty? ? '' : "FILTER (?x IN (#{concept_schemes.join(',')}))"
end

def current_schemes(concept_schemes)
if concept_schemes.nil? || concept_schemes.empty?
main_concept_scheme = get_main_concept_scheme
concept_schemes = main_concept_scheme ? [main_concept_scheme] : []
end
concept_schemes
end

end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module LinkedData
module Models
module SKOS
module ConceptSchemes
def get_main_concept_scheme(default_return: ontology_uri)
all = all_concepts_schemes
unless all.nil?
all = all.map { |x| x.id }
return default_return if all.include?(ontology_uri)
end
end

def all_concepts_schemes
LinkedData::Models::SKOS::Scheme.in(self).all
end
end
end
end
end

Loading