From fceabfcc4e281c582ec5cc09ba84eb49e20a13f0 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Thu, 16 Jul 2015 16:54:48 +0200 Subject: feature tests for standalone version --- lib/dataset.rb | 2 + lib/opentox-client.rb | 24 +++--- lib/opentox.rb | 228 ++++++++++++++------------------------------------ 3 files changed, 77 insertions(+), 177 deletions(-) (limited to 'lib') diff --git a/lib/dataset.rb b/lib/dataset.rb index c965388..1c938da 100644 --- a/lib/dataset.rb +++ b/lib/dataset.rb @@ -213,6 +213,7 @@ module OpenTox end end +=begin RDF_FORMATS.each do |format| # redefine rdf parse methods for all formats e.g. parse_rdfxml @@ -268,6 +269,7 @@ module OpenTox end end +=end # TODO: fix bug that affects data_entry positions # DG: who wrotes this comment ? def to_ntriples # redefined string version for better performance diff --git a/lib/opentox-client.rb b/lib/opentox-client.rb index bafde4c..9f3373d 100644 --- a/lib/opentox-client.rb +++ b/lib/opentox-client.rb @@ -1,14 +1,16 @@ require 'rubygems' require "bundler/setup" -require 'rdf' -require 'rdf/raptor' -require 'rdf/turtle' +#require 'rdf' +#require 'rdf/raptor' +#require 'rdf/turtle' require "rest-client" require 'uri' require 'yaml' require 'json' require 'logger' require "securerandom" +require 'mongo' +require 'bson' default_config = File.join(ENV["HOME"],".opentox","config","default.rb") client_config = File.join(ENV["HOME"],".opentox","config","opentox-client.rb") @@ -18,16 +20,16 @@ require default_config if File.exist? default_config require client_config if File.exist? client_config # define constants and global variables -RDF::OT = RDF::Vocabulary.new 'http://www.opentox.org/api/1.2#' -RDF::OT1 = RDF::Vocabulary.new 'http://www.opentox.org/api/1.1#' -RDF::OTA = RDF::Vocabulary.new 'http://www.opentox.org/algorithmTypes.owl#' -RDF::OLO = RDF::Vocabulary.new 'http://purl.org/ontology/olo/core#' -RDF::TB = RDF::Vocabulary.new "http://onto.toxbank.net/api/" -RDF::ISA = RDF::Vocabulary.new "http://onto.toxbank.net/isa/" -RDF::OWL = RDF::Vocabulary.new "http://www.w3.org/2002/07/owl#" +#RDF::OT = RDF::Vocabulary.new 'http://www.opentox.org/api/1.2#' +#RDF::OT1 = RDF::Vocabulary.new 'http://www.opentox.org/api/1.1#' +#RDF::OTA = RDF::Vocabulary.new 'http://www.opentox.org/algorithmTypes.owl#' +#RDF::OLO = RDF::Vocabulary.new 'http://purl.org/ontology/olo/core#' +#RDF::TB = RDF::Vocabulary.new "http://onto.toxbank.net/api/" +#RDF::ISA = RDF::Vocabulary.new "http://onto.toxbank.net/isa/" +#RDF::OWL = RDF::Vocabulary.new "http://www.w3.org/2002/07/owl#" CLASSES = ["Compound", "Feature", "Dataset", "Validation", "Task", "Investigation"] -RDF_FORMATS = [:rdfxml,:ntriples,:turtle] +#RDF_FORMATS = [:rdfxml,:ntriples,:turtle] # Regular expressions for parsing classification data TRUE_REGEXP = /^(true|active|1|1.0|tox|activating|carcinogen|mutagenic)$/i diff --git a/lib/opentox.rb b/lib/opentox.rb index fe49ece..b2e9c1b 100644 --- a/lib/opentox.rb +++ b/lib/opentox.rb @@ -1,31 +1,31 @@ # defaults to stderr, may be changed to file output (e.g in opentox-service) $logger = OTLogger.new(STDERR) $logger.level = Logger::DEBUG +Mongo::Logger.logger = $logger +Mongo::Logger.logger.level = Logger::WARN +$mongo = Mongo::Client.new($mongodb[:uri]) module OpenTox # Ruby interface + attr_accessor :data # Create a new OpenTox object - # @param uri [optional,String] URI + # @param id [optional,String] ID # @return [OpenTox] OpenTox object - def initialize uri=nil + def initialize @data = {} - if uri - @data["uri"] = uri.to_s.chomp - get - else - @data["uuid"] = SecureRandom.uuid - @data["uri"] = File.join(service_uri, @data["uuid"]) - @data["created_at"] = DateTime.now.to_s - @data["type"] = self.class.to_s.split('::').last - end + @data["type"] = type + end + + def created_at + # TODO from BSON::ObjectId end # Object metadata (lazy loading) # @return [Hash] Object metadata - def metadata force_update=false - get if force_update and URI.accessible? @data["uri"] + def metadata + get if exists? @data end @@ -43,167 +43,55 @@ module OpenTox # @param values [Array, String] Predicate value(s) def []=(predicate,values) predicate = predicate.to_s - @data[predicate] = [values].flatten + values.is_a?(Array) ? @data[predicate] = [values].flatten : @data[predicate] = values end -=begin - # Object parameters (lazy loading) - # {http://opentox.org/dev/apis/api-1.2/interfaces OpenTox API} - # @return [Hash] Object parameters - def parameters force_update=false - if (@parameters.empty? or force_update) and URI.accessible? @uri - get #if @rdf.empty? or force_update - params = {} - query = RDF::Query.new({ - :parameter => { - RDF.type => RDF::OT.Parameter, - :property => :value, - } - }) - query.execute(@rdf).each do |solution| - params[solution.parameter] = {} unless params[solution.parameter] - params[solution.parameter][solution.property] = solution.value - end - @parameters = params.values - end - @parameters + def id + @data["_id"] end - - # Parameter value - # @param [String] title - # @return [String] value - def parameter_value title - @parameters.collect{|p| p[RDF::OT.paramValue] if p[RDF::DC.title] == title}.compact.first + + def exists? + nr_items = $mongo[collection].find(:_id => @data["_id"]).count + nr_items > 0 ? true : false end -=end # Get object from webservice # @param [String,optional] mime_type - def get mime_type="application/json" - bad_request_error "Mime type #{mime_type} is not supported. Please use 'application/json' (default), 'text/plain' (ntriples) or mime_type == 'application/rdf+xml'." unless mime_type == "application/json" or mime_type == "text/plain" or mime_type == "application/rdf+xml" - response = RestClientWrapper.get(@data["uri"],{},{:accept => mime_type}) - if URI.task?(response) - uri = wait_for_task response - response = RestClientWrapper.get(uri,{},{:accept => mime_type}) - end - case mime_type - when 'application/json' - @data = JSON.parse(response) if response - when "text/plain" - parse_ntriples response - when "application/rdf+xml" - parse_rdfxml response - end + def get + resource_not_found_error("#{@data[:type]} with ID #{@data["_id"]} not found.") unless exists? + @data = $mongo[collection].find(:_id => @data["_id"]).first end -=begin - # Post object to webservice (append to object), rarely useful and deprecated - # @deprecated - def post wait=true, mime_type="text/plain" - bad_request_error "Mime type #{mime_type} is not supported. Please use 'text/plain' (default) or 'application/rdf+xml'." unless mime_type == "text/plain" or mime_type == "application/rdf+xml" - case mime_type - when 'text/plain' - body = self.to_ntriples - when 'application/rdf+xml' - body = self.to_rdfxml - end - #Authorization.check_policy(@uri) if $aa[:uri] - uri = RestClientWrapper.post @uri.to_s, body, { :content_type => mime_type} - wait ? wait_for_task(uri) : uri + def save + @data["_id"] = $mongo[collection].insert_one(@data).inserted_id end -=end # Save object at webservice (replace or create object) - def put wait=true, mime_type="application/json" - case mime_type - when 'application/json' - body = @data.to_json - else - bad_request_error "Mime type #{mime_type} is not supported. Please use 'application/json' (default)." - end - uri = RestClientWrapper.put @data["uri"], body, { :content_type => mime_type} - wait ? wait_for_task(uri) : uri + def put + #@data.delete("_id") # to enable updates + $mongo[collection].find(:_id => @data["_id"]).find_one_and_replace(@data, :upsert => true) end # Delete object at webservice def delete - RestClientWrapper.delete(@data["uri"]) - #Authorization.delete_policies_from_uri(@data["uri"]) if $aa[:uri] - end - - def service_uri - self.class.service_uri - end - - def create_rdf - #$logger.debug "#{eval("RDF::OT."+self.class.to_s.split('::').last)}\n" - @rdf = RDF::Graph.new - # DG: since model is no self.class anymore - @metadata[RDF.type] ||= (eval("RDF::OT."+self.class.to_s.split('::').last) =~ /Lazar|Generic/) ? RDF::URI.new(RDF::OT.Model) : RDF::URI.new(eval("RDF::OT."+self.class.to_s.split('::').last)) - #@metadata[RDF.type] ||= RDF::URI.new(eval("RDF::OT."+self.class.to_s.split('::').last)) - @metadata[RDF::DC.date] ||= DateTime.now - # DG: uri in object should be in brackets, otherwise query for uri-list ignores the object. - # see: http://www.w3.org/TR/rdf-testcases/#sec-uri-encoding - @metadata.each do |predicate,values| - [values].flatten.each{ |value| @rdf << [RDF::URI.new(@data["uri"]), predicate, (URI.valid?(value) ? RDF::URI.new(value) : value)] unless value.nil? } - end - @parameters.each do |parameter| - p_node = RDF::Node.new - @rdf << [RDF::URI.new(@data["uri"]), RDF::OT.parameters, p_node] - @rdf << [p_node, RDF.type, RDF::OT.Parameter] - parameter.each { |k,v| @rdf << [p_node, k, v] unless v.nil?} - end + $mongo[collection].find(:_id => @data["_id"]).find_one_and_delete end - - # as defined in opentox-client.rb - RDF_FORMATS.each do |format| - # rdf parse methods for all formats e.g. parse_rdfxml - send :define_method, "parse_#{format}".to_sym do |rdf| - @rdf = RDF::Graph.new - RDF::Reader.for(format).new(rdf) do |reader| - reader.each_statement{ |statement| @rdf << statement } - end - # return values as plain strings instead of RDF objects - @metadata = @rdf.to_hash[RDF::URI.new(@data["uri"])].inject({}) { |h, (predicate, values)| h[predicate] = values.collect{|v| v.to_s}; h } - end - -=begin - # rdf serialization methods for all formats e.g. to_rdfxml - send :define_method, "to_#{format}".to_sym do - create_rdf - # if encoding is used iteration is necessary - # see: http://rubydoc.info/github/ruby-rdf/rdf/RDF/NTriples/Writer - RDF::Writer.for(format).buffer(:encoding => Encoding::ASCII) do |writer| - @rdf.each_statement do |statement| - writer << statement - end - end - end -=end - end - - # @return [String] converts object to turtle-string - def to_turtle # redefined to use prefixes (not supported by RDF::Writer) - prefixes = {:rdf => "http://www.w3.org/1999/02/22-rdf-syntax-ns#"} - ['OT', 'DC', 'XSD', 'OLO'].each{|p| prefixes[p.downcase.to_sym] = eval("RDF::#{p}.to_s") } - create_rdf - RDF::Turtle::Writer.for(:turtle).buffer(:prefixes => prefixes) do |writer| - writer << @rdf - end + # @return [String] converts OpenTox object into html document (by first converting it to a string) + def to_html + @data.to_json.to_html end - def to_json - @data.to_json + def type + self.class.to_s.split('::').last end - # @return [String] converts OpenTox object into html document (by first converting it to a string) - def to_html - to_json.to_html + def collection + type.downcase end # short access for metadata keys title, description and type - [ :title , :description , :type , :uri, :uuid ].each do |method| + [ :title , :description ].each do |method| send :define_method, method do self[method] end @@ -218,12 +106,6 @@ module OpenTox end module ClassMethods - def service_uri - service = self.to_s.split('::')[1].downcase - eval("$#{service}[:uri]") - rescue - bad_request_error "$#{service}[:uri] variable not set. Please set $#{service}[:uri] or use an explicit uri as first constructor argument " - end def subjectid RestClientWrapper.subjectid end @@ -239,30 +121,44 @@ module OpenTox include OpenTox def self.all - uris = RestClientWrapper.get(service_uri, {},{:accept => 'text/uri-list'}).split("\n").compact - uris.collect{|uri| self.new(uri)} + $mongo[collection].find.collect do |data| + f = self.new + f.data = data + f + end + end + + def self.find_id id + self.find(:_id => id) end #@example fetching a model - # OpenTox::Model.find() -> model-object - def self.find uri - URI.accessible?(uri) ? self.new(uri) : nil + # OpenTox::Model.find() -> model-object + def self.find metadata + f = self.new + items = $mongo[collection].find metadata + items.count > 0 ? f.data = items.first : f = nil + f end def self.create metadata object = self.new - metadata.each{|k,v| object[k] = v} - object.put + object.data = metadata + object.save + object.get object end def self.find_or_create metadata search = metadata search.delete("_id") - search.delete("uri") - search.delete("uuid") - uris = RestClientWrapper.get(service_uri,{:query => search},{:accept => "text/uri-list"}).split("\n") - uris.empty? ? self.create(metadata) : self.new(uris.first) + ids = $mongo[collection].find(search).distinct(:_id) + ids.empty? ? self.create(metadata) : self.find_id(ids.first) + end + + private + def self.collection + self.to_s.split('::').last.downcase end end OpenTox.const_set klass,c -- cgit v1.2.3