1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
require "nokogiri"
# OpenTox module
module OpenTox
#Class for QMRF reporting.
#
#Provides a ruby OpenTox class to prepare an initial version of a QMRF report.
#The XML output is in QMRF version 1.3 and can be finalized with the QMRF editor 2.0 (https://sourceforge.net/projects/qmrf/)
#@example Report
# require "qsar-report"
# report = OpenTox::QMRFReport.new
# report.Value "QSAR_title", "My QSAR Title"
# report.change_catalog :publications_catalog, :publications_catalog_1, {:title => "MyName M (2016) My Publication Title, QSAR News, 10, 14-22", :url => "http://myqsarnewsmag.dom"}
# report.ref_catalog :bibliography, :publications_catalog, :publications_catalog_1
# puts report.to_xml
class QMRFReport
# QMRF XML Schema file
SCHEMA_FILE = File.join(File.dirname(__FILE__),"template/qmrf.xsd")
# QMRF XML Template file
TEMPLATE_FILE = File.join(File.dirname(__FILE__),"template/qmrf.xml")
attr_accessor :xml, :report
# Open an existing QMRF xml report
# @param [String] file Name of the file
def open file
xml = File.read("#{file}")
@report = Nokogiri.XML(xml)
end
# Initialize a new report instance from qmrf template
def initialize
xml = File.read(TEMPLATE_FILE)
@report = Nokogiri.XML(xml)
end
# returns XML representation (QMRF XML report) of report instance
# @return [String] returns XML
def to_xml
@report.to_xml
end
# Get or Set a value
# e.G.: <QSAR_title chapter="1.1" help="" name="QSAR identifier (title)">Title of My QSAR</QSAR_title>
# @param [String] key Nodename e.g.: "QSAR_title"
# @param [String] value Value to change. If not set the function returns the current value
# @return [Error] returns Error message if fails
# @return [String] returns value
def Value key, value=nil
raise "Can not edit attribute #{key} directly. Edit the catalog with 'report.change_catalog(catalog, key, value)'." if ["QSAR_software","QSAR_Algorithm", ""].include? key
t = @report.at_css key
t.content = value unless value.nil?
t.content
end
# Change a catalog
# @param [String] catalog Name of the catalog - One of "software_catalog", "algorithms_catalog", "descriptors_catalog", "endpoints_catalog", "publications_catalog", "authors_catalog" in QMRF v1.3
# @param [String] id Single entry node in the catalog e.G.: "<software contact='mycontact@mydomain.dom' description="My QSAR Software " id="software_catalog_2" name="MySoftware" number="" url="https://mydomain.dom"/>
# @param [Hash] valuehash Key-Value Hash with attributes for a single catalog node
# @return [Error] returns Error message if fails
def change_catalog catalog, id, valuehash
catalog_exists? catalog
if @report.at_css("#{catalog}").at("//*[@id='#{id}']")
valuehash.each do |key, value|
@report.at_css("#{catalog}").at("//*[@id='#{id}']")["#{key}"]= value
end
else
cat = @report.at_css("#{catalog}")
newentry = Nokogiri::XML::Node.new("#{catalog.to_s.gsub(/s?_catalog/,'')}", self.report)
newentry["id"] = id
valuehash.each do |key, value|
newentry["#{key}"] = value
end
cat << newentry
end
end
# Set reference to a catalog entry.
# e.g.: reference an author entry from authors_catalog to Chapter 2.2 QMRF authors
#@example ref_catalog
# report.ref_catalog 'qmrf_authors', 'authors_catalog', 'firstauthor'
# @param [String] chapter Name of the chapter to add the catalog reference. e.g.: qmrf_authors, model_authors, QSAR_software, ...
# @param [String] catalog Name of the catalog
# @param [String] id entry node in the catalog
def ref_catalog chapter, catalog, id
catalog_exists? catalog
if @report.at_css("#{catalog}").at("//*[@id='#{id}']")
chap = @report.at_css("#{chapter}")
if chap.at("//*[@idref='#{id}']").nil?
newentry = Nokogiri::XML::Node.new("#{catalog.to_s.gsub(/s?_catalog/,'_ref')}", self.report)
newentry["idref"] = id
chap << newentry
end
else
raise "catalog entry with id: #{id} do not exist."
end
end
# get an attribute from a catalog entry
# @param [String] catalog Name of the catalog
# @param [String] id entry id in the catalog
# @param [String] key returns value of a key in a catalog node
# @return [String, false] returns value of a key in a catalog node or false if catalog entry do not exists.
def get_catalog_value catalog, id, key
catalog_exists? catalog
if @report.at_css("#{catalog}").at("//*[@id='#{id}']")
@report.at_css("#{catalog}").at("//*[@id='#{id}']")["#{key}"]
else
return false
end
end
# Check if a catalog exists in this QMRF version
# @param [String] catalog Catalog
# @return [Error, true] returns true or Error if a catalog do not exists
def catalog_exists? catalog
raise "Unknown catalog: #{catalog}" unless ["software_catalog", "algorithms_catalog", "descriptors_catalog", "endpoints_catalog", "publications_catalog", "authors_catalog"].include? catalog.to_s
true
end
# Validates a report instance against qmrf.xsd (XML Structure Definition)
def validate
xsd = Nokogiri::XML::Schema(File.read(SCHEMA_FILE))
out = ""
xsd.validate(@report).each do |error|
out << error.message unless error.message == "Element 'algorithm', attribute 'publication_ref': '' is not a valid value of the atomic type 'xs:IDREF'." || error.message == "Element 'descriptor', attribute 'publication_ref': '' is not a valid value of the atomic type 'xs:IDREF'."
# @todo ignore case sensitivity error: error.message The value 'NO' is not an.Element of the set {'Yes', 'No'}.
end
return out
end
end
end
|