require 'erb' require 'rdf' require 'rdf/vocab' require 'rdf/jena' require_relative 'reader' require_relative 'lru_reader' require_relative 'concept' require_relative 'concept_scheme' module BELParser module Resource class JenaTDBReader include Reader prepend LRUReader BELV = RDF::Vocabulary.new('http://www.openbel.org/vocabulary/') SKOS = RDF::Vocab::SKOS DC = RDF::Vocab::DC VALUE_PREDICATE_ORDER = [ SKOS.prefLabel, DC.identifier, DC.title, SKOS.altLabel ] def initialize(tdb_directory_path) @rdf = RDF::Jena::Repository.new(tdb_directory_path) end def retrieve_resource(identifier) uri = RDF::URI(identifier) domain, prefix, pref_label = nil types = [] @rdf.query([:subject => uri]).each do |solution| case solution.predicate when RDF.type types << solution.object when BELV.domain domain = solution.object.to_s when BELV.prefix prefix = solution.object.to_s when SKOS.prefLabel pref_label = solution.object.to_s end end return nil unless types.any?(&method(:scheme_class?)) ConceptScheme.new(uri.to_s, domain, prefix, pref_label, types.map(&:to_s)) end def retrieve_value_from_resource(identifier, value) concept_scheme = retrieve_resource(identifier) return nil unless concept_scheme template_binding = binding sparql_query = RESOLVE_CONCEPT.result(template_binding) to_concept = method(:hash_to_concept).to_proc.curry[concept_scheme] @rdf.query_execute(sparql_query).map(&to_concept) end def retrieve_values_from_resource(identifier) concept_scheme = retrieve_resource(identifier) return nil unless concept_scheme template_binding = binding sparql_query = RESOLVE_CONCEPTS.result(template_binding) to_concept = method(:hash_to_concept).to_proc.curry[concept_scheme] @rdf.query_execute(sparql_query).map(&to_concept) end private def scheme_class?(uri) uri == BELV.AnnotationConceptScheme || uri == BELV.NamespaceConceptScheme end def find_value_uris(resource_uri, value) VALUE_PREDICATE_ORDER.each do |predicate| subjects = @rdf.query([:predicate => predicate, :object => value]) .select do |stmt| @rdf.has_statement?( RDF::Statement(stmt.subject, SKOS.inScheme, resource_uri)) end.map(&:subject) if !subjects.empty? return subjects end end [] end def hash_to_concept(concept_scheme, hash) Concept.new(concept_scheme, *hash.values_at('concept', 'prefLabel', 'identifier', 'title', 'altLabels', 'types')) end RESOLVE_CONCEPT = ERB.new(<<-SPARQL) prefix belv: prefix dct: prefix rdf: prefix skos: select ?concept ?prefLabel ?identifier ?title (group_concat(distinct(?type);separator='|') as ?types) (group_concat(distinct(?altLabel);separator='|') as ?altLabels) where { {?concept skos:prefLabel "<%= value %>"} UNION {?concept dct:identifier "<%= value %>"} UNION {?concept dct:title "<%= value %>"} UNION {?concept skos:altLabel "<%= value %>"} ?concept skos:inScheme <<%= identifier %>> . ?concept rdf:type ?type . ?concept skos:prefLabel ?prefLabel . ?concept dct:identifier ?identifier . optional { ?concept dct:title ?title . ?concept skos:altLabel ?altLabel . } } group by ?concept ?prefLabel ?identifier ?title SPARQL RESOLVE_CONCEPTS = ERB.new(<<-SPARQL) prefix belv: prefix dct: prefix rdf: prefix skos: select ?concept ?prefLabel ?identifier ?title (group_concat(distinct(?type);separator='|') as ?types) (group_concat(distinct(?altLabel);separator='|') as ?altLabels) where { ?concept skos:inScheme <<%= identifier %>> . ?concept rdf:type ?type . ?concept skos:prefLabel ?prefLabel . optional { ?concept dct:identifier ?identifier . ?concept dct:title ?title . ?concept skos:altLabel ?altLabel } } group by ?concept ?prefLabel ?identifier ?title SPARQL #ConceptScheme class ConceptScheme include Dataset attr_reader :identifier, :domain, :keyword, :name, :types def initialize(uri, domain, prefix, name, types) @identifier = uri @domain = domain.to_s @keyword = prefix.to_s @name = name.to_s @types = convert_types(types) end private def convert_types(types) types.map do |type| case type when BELV.NamespaceConceptScheme Dataset::NAMESPACE when BELV.AnnotationConceptScheme Dataset::ANNOTATION end end.compact end end class Concept include Value attr_reader :dataset, :uri, :name, :identifier, :title, :synonyms, :encodings def initialize(dataset, uri, pref_label, identifier, title, alt_labels, types) @dataset = dataset @uri = uri @name = pref_label.to_s @identifier = identifier.to_s @title = title.to_s @synonyms = if alt_labels.respond_to?(:each) alt_labels.map(&:to_s) else alt_labels.to_s.split('|') end @encodings = if types.respond_to?(:each) convert_encoding_types(types.map(&:to_s)) else convert_encoding_types(types.to_s.split('|')) end end private def convert_encoding_types(types) types.map do |type| case type when BELV.AbundanceConcept :A when BELV.BiologicalProcessConcept :B when BELV.ComplexConcept :C when BELV.GeneConcept :G when BELV.LocationConcept :L when BELV.MicroRNAConcept :M when BELV.MolecularActivityConcept :T when BELV.PathologyConcept :O when BELV.ProteinConcept :P when BELV.ProteinModificationConcept :E when BELV.RNAConcept :R end end.compact end end end end end if __FILE__ == $PROGRAM_NAME reader = BELParser::Resource::JenaTDBReader.new( '/home/tony/projects/openbel/resource-reasoner/biological-concepts-db') reader.retrieve_resource('http://www.openbel.org/bel/namespace/hgnc-human-genes') end