opentox-ruby 0.0.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/parser.rb CHANGED
@@ -29,22 +29,37 @@ module OpenTox
29
29
 
30
30
  # Read metadata from opentox service
31
31
  # @return [Hash] Object metadata
32
- def load_metadata
33
-
34
- if @dataset
35
- uri = File.join(@uri,"metadata")
32
+ def load_metadata(subjectid=nil)
33
+ # avoid using rapper directly because of 2 reasons:
34
+ # * http errors wont be noticed
35
+ # * subjectid cannot be sent as header
36
+ ##uri += "?subjectid=#{CGI.escape(subjectid)}" if subjectid
37
+ ## `rapper -i rdfxml -o ntriples #{uri} 2>/dev/null`.each_line do |line|
38
+ if File.exist?(@uri)
39
+ file = File.new(@uri)
36
40
  else
37
- uri = @uri
41
+ file = Tempfile.new("ot-rdfxml")
42
+ if @dataset
43
+ # do not concat /metadata to uri string, this would not work for dataset/R401577?max=3
44
+ uri = URI::parse(@uri)
45
+ uri.path = File.join(uri.path,"metadata")
46
+ uri = uri.to_s
47
+ else
48
+ uri = @uri
49
+ end
50
+ file.puts OpenTox::RestClientWrapper.get uri,{:subjectid => subjectid,:accept => "application/rdf+xml"},nil,false
51
+ file.close
52
+ to_delete = file.path
38
53
  end
39
-
40
54
  statements = []
41
55
  parameter_ids = []
42
- `rapper -i rdfxml -o ntriples #{uri} 2>/dev/null`.each_line do |line|
56
+ `rapper -i rdfxml -o ntriples #{file.path} 2>/dev/null`.each_line do |line|
43
57
  triple = line.to_triple
44
58
  @metadata[triple[1]] = triple[2].split('^^').first if triple[0] == @uri and triple[1] != RDF['type']
45
59
  statements << triple
46
60
  parameter_ids << triple[2] if triple[1] == OT.parameters
47
61
  end
62
+ File.delete(to_delete) if to_delete
48
63
  unless parameter_ids.empty?
49
64
  @metadata[OT.parameters] = []
50
65
  parameter_ids.each do |p|
@@ -55,10 +70,45 @@ module OpenTox
55
70
  end
56
71
  @metadata
57
72
  end
58
-
73
+
74
+ # creates owl object from rdf-data
75
+ # @param [String] rdf
76
+ # @param [String] type of the info (e.g. OT.Task, OT.ErrorReport) needed to get the subject-uri
77
+ # @return [Owl] with uri and metadata set
78
+ def self.from_rdf( rdf, type )
79
+ # write to file and read convert with rapper into tripples
80
+ file = Tempfile.new("ot-rdfxml")
81
+ file.puts rdf
82
+ file.close
83
+ #puts "cmd: rapper -i rdfxml -o ntriples #{file} 2>/dev/null"
84
+ triples = `rapper -i rdfxml -o ntriples #{file.path} 2>/dev/null`
85
+
86
+ # load uri via type
87
+ uri = nil
88
+ triples.each_line do |line|
89
+ triple = line.to_triple
90
+ if triple[1] == RDF['type'] and triple[2]==type
91
+ raise "uri already set, two uris found with type: "+type.to_s if uri
92
+ uri = triple[0]
93
+ end
94
+ end
95
+ File.delete(file.path)
96
+ # load metadata
97
+ metadata = {}
98
+ triples.each_line do |line|
99
+ triple = line.to_triple
100
+ metadata[triple[1]] = triple[2].split('^^').first if triple[0] == uri and triple[1] != RDF['type']
101
+ end
102
+ owl = Owl::Generic.new(uri)
103
+ owl.metadata = metadata
104
+ owl
105
+ end
106
+
59
107
  # Generic parser for all OpenTox classes
60
108
  class Generic
61
109
  include Owl
110
+
111
+ attr_accessor :uri, :metadata
62
112
  end
63
113
 
64
114
  # OWL-DL parser for datasets
@@ -71,9 +121,9 @@ module OpenTox
71
121
  # Create a new OWL-DL dataset parser
72
122
  # @param uri Dataset URI
73
123
  # @return [OpenTox::Parser::Owl::Dataset] OWL-DL parser
74
- def initialize(uri)
124
+ def initialize(uri, subjectid=nil)
75
125
  super uri
76
- @dataset = ::OpenTox::Dataset.new(@uri)
126
+ @dataset = ::OpenTox::Dataset.new(@uri, subjectid)
77
127
  end
78
128
 
79
129
  # Read data from dataset service. Files can be parsed by setting #uri to a filename (after initialization with a real URI)
@@ -87,12 +137,27 @@ module OpenTox
87
137
  # dataset = parser.load_uri
88
138
  # dataset.save
89
139
  # @return [Hash] Internal dataset representation
90
- def load_uri
140
+ def load_uri(subjectid=nil)
141
+
142
+ # avoid using rapper directly because of 2 reasons:
143
+ # * http errors wont be noticed
144
+ # * subjectid cannot be sent as header
145
+ ##uri += "?subjectid=#{CGI.escape(subjectid)}" if subjectid
146
+ ##`rapper -i rdfxml -o ntriples #{file} 2>/dev/null`.each_line do |line|
147
+ if File.exist?(@uri)
148
+ file = File.new(@uri)
149
+ else
150
+ file = Tempfile.new("ot-rdfxml")
151
+ file.puts OpenTox::RestClientWrapper.get @uri,{:subjectid => subjectid,:accept => "application/rdf+xml"},nil,false
152
+ file.close
153
+ to_delete = file.path
154
+ end
155
+
91
156
  data = {}
92
157
  feature_values = {}
93
158
  feature = {}
94
159
  other_statements = {}
95
- `rapper -i rdfxml -o ntriples #{@uri} 2>/dev/null`.each_line do |line|
160
+ `rapper -i rdfxml -o ntriples #{file.path} 2>/dev/null`.each_line do |line|
96
161
  triple = line.chomp.split(' ',3)
97
162
  triple = triple[0..2].collect{|i| i.sub(/\s+.$/,'').gsub(/[<>"]/,'')}
98
163
  case triple[1]
@@ -105,32 +170,62 @@ module OpenTox
105
170
  data[triple[0]] = {:compound => "", :values => []} unless data[triple[0]]
106
171
  data[triple[0]][:compound] = triple[2]
107
172
  when /#{OT.feature}/i
108
- feature[triple[0]] = triple[2]
173
+ feature[triple[0]] = triple[2]
174
+ when /#{RDF.type}/i
175
+ if triple[2]=~/#{OT.Compound}/i and !data[triple[0]]
176
+ data[triple[0]] = {:compound => triple[0], :values => []}
177
+ end
109
178
  else
110
179
  end
111
180
  end
181
+ File.delete(to_delete) if to_delete
112
182
  data.each do |id,entry|
113
- entry[:values].each do |value_id|
114
- value = feature_values[value_id].split(/\^\^/).first # remove XSD.type
115
- @dataset.add entry[:compound],feature[value_id],value
183
+ if entry[:values].size==0
184
+ # no feature values add plain compounds
185
+ @dataset.add_compound(entry[:compound])
186
+ else
187
+ entry[:values].each do |value_id|
188
+ split = feature_values[value_id].split(/\^\^/)
189
+ case split[-1]
190
+ when XSD.double, XSD.float
191
+ value = split.first.to_f
192
+ when XSD.boolean
193
+ value = split.first=~/(?i)true/ ? true : false
194
+ else
195
+ value = split.first
196
+ end
197
+ @dataset.add entry[:compound],feature[value_id],value
198
+ end
116
199
  end
117
200
  end
118
- load_features
119
- @dataset.metadata = load_metadata
201
+ load_features subjectid
202
+ @dataset.metadata = load_metadata(subjectid)
120
203
  @dataset
121
204
  end
122
205
 
123
206
  # Read only features from a dataset service.
124
207
  # @return [Hash] Internal features representation
125
- def load_features
126
- uri = File.join(@uri,"features")
208
+ def load_features(subjectid=nil)
209
+ if File.exist?(@uri)
210
+ file = File.new(@uri)
211
+ else
212
+ file = Tempfile.new("ot-rdfxml")
213
+ # do not concat /features to uri string, this would not work for dataset/R401577?max=3
214
+ uri = URI::parse(@uri)
215
+ uri.path = File.join(uri.path,"features")
216
+ uri = uri.to_s
217
+ file.puts OpenTox::RestClientWrapper.get uri,{:subjectid => subjectid,:accept => "application/rdf+xml"},nil,false
218
+ file.close
219
+ to_delete = file.path
220
+ end
127
221
  statements = []
128
222
  features = Set.new
129
- `rapper -i rdfxml -o ntriples #{uri} 2>/dev/null`.each_line do |line|
223
+ `rapper -i rdfxml -o ntriples #{file.path} 2>/dev/null`.each_line do |line|
130
224
  triple = line.chomp.split('> ').collect{|i| i.sub(/\s+.$/,'').gsub(/[<>"]/,'')}[0..2]
131
225
  statements << triple
132
- features << triple[0] if triple[1] == RDF['type'] and triple[2] == OT.Feature
226
+ features << triple[0] if triple[1] == RDF['type'] and (triple[2] == OT.Feature || triple[2] == OT.NumericFeature)
133
227
  end
228
+ File.delete(to_delete) if to_delete
134
229
  statements.each do |triple|
135
230
  if features.include? triple[0]
136
231
  @dataset.features[triple[0]] = {} unless @dataset.features[triple[0]]
data/lib/policy.rb ADDED
@@ -0,0 +1,261 @@
1
+ module OpenTox
2
+ require "rexml/document"
3
+
4
+ #Module for policy-processing
5
+ # @see also http://www.opentox.org/dev/apis/api-1.2/AA for opentox API specs
6
+ # Class Policies corresponds to <policies> container of an xml-policy-fle
7
+ class Policies
8
+
9
+ attr_accessor :name, :policies
10
+
11
+ def initialize()
12
+ @policies = {}
13
+ end
14
+
15
+ #create new policy instance with name
16
+ # @param [String]name of the policy
17
+ def new_policy(name)
18
+ @policies[name] = Policy.new(name)
19
+ end
20
+
21
+ #drop a specific policy in a policies instance
22
+ # @param [String]name of the policy
23
+ # @return [Boolean]
24
+ def drop_policy(name)
25
+ return true if @policies.delete(name)
26
+ end
27
+
28
+ #drop all policies in a policies instance
29
+ def drop_policies
30
+ @policies.each do |name, policy|
31
+ drop_policy(name)
32
+ end
33
+ return true
34
+ end
35
+
36
+ # @return [Array] set of arrays affected by policies
37
+ def uris
38
+ @policies.collect{ |k,v| v.uris }.flatten.uniq
39
+ end
40
+
41
+ #drop all policies in a policies instance
42
+ def names
43
+ out = []
44
+ @policies.each do |name, policy|
45
+ out << name
46
+ end
47
+ return out
48
+ end
49
+
50
+ #loads a default policy template in policies instance
51
+ def load_default_policy(user, uri, group="member")
52
+ template = case user
53
+ when "guest", "anonymous" then "default_guest_policy"
54
+ else "default_policy"
55
+ end
56
+ xml = File.read(File.join(File.dirname(__FILE__), "templates/#{template}.xml"))
57
+ self.load_xml(xml)
58
+ datestring = Time.now.strftime("%Y-%m-%d-%H-%M-%S-x") + rand(1000).to_s
59
+
60
+ @policies["policy_user"].name = "policy_user_#{user}_#{datestring}"
61
+ @policies["policy_user"].rules["rule_user"].uri = uri
62
+ @policies["policy_user"].rules["rule_user"].name = "rule_user_#{user}_#{datestring}"
63
+ @policies["policy_user"].subjects["subject_user"].name = "subject_user_#{user}_#{datestring}"
64
+ @policies["policy_user"].subjects["subject_user"].value = "uid=#{user},ou=people,dc=opentox,dc=org"
65
+ @policies["policy_user"].subject_group = "subjects_user_#{user}_#{datestring}"
66
+
67
+ @policies["policy_group"].name = "policy_group_#{group}_#{datestring}"
68
+ @policies["policy_group"].rules["rule_group"].uri = uri
69
+ @policies["policy_group"].rules["rule_group"].name = "rule_group_#{group}_#{datestring}"
70
+ @policies["policy_group"].subjects["subject_group"].name = "subject_group_#{group}_#{datestring}"
71
+ @policies["policy_group"].subjects["subject_group"].value = "cn=#{group},ou=groups,dc=opentox,dc=org"
72
+ @policies["policy_group"].subject_group = "subjects_#{group}_#{datestring}"
73
+ return true
74
+ end
75
+
76
+ #loads a xml template
77
+ def load_xml(xml)
78
+ rexml = REXML::Document.new(xml)
79
+ rexml.elements.each("Policies/Policy") do |pol| #Policies
80
+ policy_name = pol.attributes["name"]
81
+ new_policy(policy_name)
82
+ #@policies[policy_name] = Policy.new(policy_name)
83
+ rexml.elements.each("Policies/Policy[@name='#{policy_name}']/Rule") do |r| #Rules
84
+ rule_name = r.attributes["name"]
85
+ uri = rexml.elements["Policies/Policy[@name='#{policy_name}']/Rule[@name='#{rule_name}']/ResourceName"].attributes["name"]
86
+ @policies[policy_name].rules[rule_name] = @policies[policy_name].new_rule(rule_name, uri)
87
+ rexml.elements.each("Policies/Policy[@name='#{policy_name}']/Rule[@name='#{rule_name}']/AttributeValuePair") do |attribute_pairs|
88
+ action=nil; value=nil;
89
+ attribute_pairs.each_element do |elem|
90
+ action = elem.attributes["name"] if elem.attributes["name"]
91
+ value = elem.text if elem.text
92
+ end
93
+ if action and value
94
+ case action
95
+ when "GET"
96
+ @policies[policy_name].rules[rule_name].get = value
97
+ when "POST"
98
+ @policies[policy_name].rules[rule_name].post = value
99
+ when "PUT"
100
+ @policies[policy_name].rules[rule_name].put = value
101
+ when "DELETE"
102
+ @policies[policy_name].rules[rule_name].delete = value
103
+ end
104
+ end
105
+ end
106
+ end
107
+ rexml.elements.each("Policies/Policy[@name='#{policy_name}']/Subjects") do |subjects| #Subjects
108
+ @policies[policy_name].subject_group = subjects.attributes["name"]
109
+ rexml.elements.each("Policies/Policy[@name='#{policy_name}']/Subjects[@name='#{@policies[policy_name].subject_group}']/Subject") do |s| #Subject
110
+ subject_name = s.attributes["name"]
111
+ subject_type = s.attributes["type"]
112
+ subject_value = rexml.elements["Policies/Policy[@name='#{policy_name}']/Subjects[@name='#{@policies[policy_name].subject_group}']/Subject[@name='#{subject_name}']/AttributeValuePair/Value"].text
113
+ @policies[policy_name].new_subject(subject_name, subject_type, subject_value) if subject_name and subject_type and subject_value
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ #generates xml from policies instance
120
+ def to_xml
121
+ doc = REXML::Document.new()
122
+ doc << REXML::DocType.new("Policies", "PUBLIC \"-//Sun Java System Access Manager7.1 2006Q3\n Admin CLI DTD//EN\" \"jar://com/sun/identity/policy/policyAdmin.dtd\"")
123
+ doc.add_element(REXML::Element.new("Policies"))
124
+
125
+ @policies.each do |name, pol|
126
+ policy = REXML::Element.new("Policy")
127
+ policy.attributes["name"] = pol.name
128
+ policy.attributes["referralPolicy"] = false
129
+ policy.attributes["active"] = true
130
+ @policies[name].rules.each do |r,rl|
131
+ rule = @policies[name].rules[r]
132
+ out_rule = REXML::Element.new("Rule")
133
+ out_rule.attributes["name"] = rule.name
134
+ servicename = REXML::Element.new("ServiceName")
135
+ servicename.attributes["name"]="iPlanetAMWebAgentService"
136
+ out_rule.add_element(servicename)
137
+ rescourcename = REXML::Element.new("ResourceName")
138
+ rescourcename.attributes["name"] = rule.uri
139
+ out_rule.add_element(rescourcename)
140
+
141
+ ["get","post","delete","put"].each do |act|
142
+ if rule.method(act).call
143
+ attribute = REXML::Element.new("Attribute")
144
+ attribute.attributes["name"] = act.upcase
145
+ attributevaluepair = REXML::Element.new("AttributeValuePair")
146
+ attributevaluepair.add_element(attribute)
147
+ attributevalue = REXML::Element.new("Value")
148
+ attributevaluepair.add_element(attributevalue)
149
+ attributevalue.add_text REXML::Text.new(rule.method(act).call)
150
+ out_rule.add_element(attributevaluepair)
151
+
152
+ end
153
+ end
154
+ policy.add_element(out_rule)
155
+ end
156
+
157
+ subjects = REXML::Element.new("Subjects")
158
+ subjects.attributes["name"] = pol.subject_group
159
+ subjects.attributes["description"] = ""
160
+ @policies[name].subjects.each do |subj, subjs|
161
+ subject = REXML::Element.new("Subject")
162
+ subject.attributes["name"] = pol.subjects[subj].name
163
+ subject.attributes["type"] = pol.subjects[subj].type
164
+ subject.attributes["includeType"] = "inclusive"
165
+ attributevaluepair = REXML::Element.new("AttributeValuePair")
166
+ attribute = REXML::Element.new("Attribute")
167
+ attribute.attributes["name"] = "Values"
168
+ attributevaluepair.add_element(attribute)
169
+ attributevalue = REXML::Element.new("Value")
170
+ attributevalue.add_text REXML::Text.new(pol.subjects[subj].value)
171
+ attributevaluepair.add_element(attributevalue)
172
+ subject.add_element(attributevaluepair)
173
+ subjects.add_element(subject)
174
+ end
175
+ policy.add_element(subjects)
176
+ doc.root.add_element(policy)
177
+ end
178
+ out = ""
179
+ doc.write(out, 2)
180
+ return out
181
+ end
182
+
183
+ end
184
+
185
+ #single policy in a policies instance
186
+ class Policy
187
+
188
+ attr_accessor :name, :rules, :subject_group, :subjects
189
+
190
+ def initialize(name)
191
+ @name = name
192
+ @rules = {}
193
+ @subject_group = ""
194
+ @subjects = {}
195
+ end
196
+
197
+ #create a new rule instance for the policy
198
+ def new_rule(name, uri)
199
+ @rules[name] = Rule.new(name, uri)
200
+ end
201
+
202
+ #create a new subject instance for the policy
203
+ def new_subject(name, type, value)
204
+ @subjects[name] = Subject.new(name, type, value)
205
+ end
206
+
207
+ # @return [Array] set of uris affected by policy
208
+ def uris
209
+ @rules.collect{ |k,v| v.uri }.uniq
210
+ end
211
+
212
+ #rule inside a policy
213
+ class Rule
214
+
215
+ attr_accessor :name, :uri, :get, :post, :put, :delete
216
+
217
+ def initialize(name, uri)
218
+ @name = name
219
+ @uri = uri
220
+ end
221
+
222
+ def rename(new, old)
223
+ self[new] = self.delete(old)
224
+ self[new].name = new
225
+ end
226
+
227
+ def get=(value)
228
+ @get = check_value(value, @get)
229
+ end
230
+
231
+ def post=(value)
232
+ @post = check_value(value, @post)
233
+ end
234
+
235
+ def delete=(value)
236
+ @delete = check_value(value, @delete)
237
+ end
238
+
239
+ def put=(value)
240
+ @put = check_value(value, @put)
241
+ end
242
+
243
+ private
244
+ #checks if value is allow or deny. returns old value if not valid.
245
+ def check_value(new_value, old_value)
246
+ return (new_value=="allow" || new_value=="deny" || new_value==nil) ? new_value : old_value
247
+ end
248
+ end
249
+
250
+ class Subject
251
+
252
+ attr_accessor :name, :type, :value
253
+
254
+ def initialize(name, type, value)
255
+ @name = name
256
+ @type = type
257
+ @value = value
258
+ end
259
+ end
260
+ end
261
+ end