opentox-ruby 0.0.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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