omf_sfa 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/omf-sfa/am/am-rest/rest_handler.rb +32 -33
- data/lib/omf-sfa/am/default_authorizer.rb +1 -0
- data/lib/omf-sfa/resource/oproperty.rb +228 -74
- data/lib/omf-sfa/resource/oresource.rb +31 -17
- data/lib/omf-sfa/version.rb +1 -1
- data/omf_sfa.gemspec +2 -1
- metadata +2 -18
@@ -2,16 +2,10 @@
|
|
2
2
|
|
3
3
|
require 'nokogiri'
|
4
4
|
require 'uuid'
|
5
|
-
# require 'omf-sfa/resource/sliver'
|
6
|
-
# require 'omf-sfa/resource/node'
|
7
|
-
# require 'omf-sfa/resource/link'
|
8
|
-
# require 'omf-sfa/resource/interface'
|
9
|
-
|
10
5
|
require 'set'
|
11
6
|
require 'json'
|
12
7
|
|
13
8
|
require 'omf_base/lobject'
|
14
|
-
require 'omf-sfa/am/am_manager'
|
15
9
|
|
16
10
|
|
17
11
|
module OMF::SFA::AM::Rest
|
@@ -96,6 +90,10 @@ module OMF::SFA::AM::Rest
|
|
96
90
|
@@service_name = name
|
97
91
|
end
|
98
92
|
|
93
|
+
def self.service_name()
|
94
|
+
@@service_name || "Unknown Service"
|
95
|
+
end
|
96
|
+
|
99
97
|
def self.load_api_template(fname)
|
100
98
|
@@html_template = File::read(fname)
|
101
99
|
end
|
@@ -106,8 +104,6 @@ module OMF::SFA::AM::Rest
|
|
106
104
|
|
107
105
|
|
108
106
|
def initialize(opts = {})
|
109
|
-
#puts "INIT>>> #{am_manager}::#{self}"
|
110
|
-
# @am_manager = am_manager
|
111
107
|
@opts = opts
|
112
108
|
end
|
113
109
|
|
@@ -115,6 +111,13 @@ module OMF::SFA::AM::Rest
|
|
115
111
|
begin
|
116
112
|
Thread.current[:http_host] = env["HTTP_HOST"]
|
117
113
|
req = ::Rack::Request.new(env)
|
114
|
+
if req.request_method == 'OPTIONS'
|
115
|
+
return [200 ,{
|
116
|
+
'Access-Control-Allow-Origin' => '*' ,
|
117
|
+
'Access-Control-Allow-Methods' => 'GET, POST, OPTIONS',
|
118
|
+
'Access-Control-Allow-Headers' => 'origin, x-csrftoken, content-type, accept'
|
119
|
+
}, ""]
|
120
|
+
end
|
118
121
|
content_type, body = dispatch(req)
|
119
122
|
if req['_format'] == 'html'
|
120
123
|
#body = self.class.convert_to_html(body, env, Set.new((@coll_handlers || {}).keys))
|
@@ -123,14 +126,15 @@ module OMF::SFA::AM::Rest
|
|
123
126
|
elsif content_type == 'application/json'
|
124
127
|
body = JSON.pretty_generate(body)
|
125
128
|
end
|
126
|
-
return [200 ,{'Content-Type' => content_type}, body + "\n"]
|
129
|
+
#return [200 ,{'Content-Type' => content_type}, body + "\n"]
|
130
|
+
return [200 ,{'Content-Type' => content_type, 'Access-Control-Allow-Origin' => '*' , 'Access-Control-Allow-Methods' => 'GET, POST, OPTIONS' }, body + "\n"]
|
127
131
|
rescue RackException => rex
|
128
132
|
return rex.reply
|
129
133
|
rescue RedirectException => rex
|
130
134
|
debug "Redirecting to #{rex.path}"
|
131
135
|
return [301, {'Location' => rex.path, "Content-Type" => ""}, ['Next window!']]
|
132
|
-
rescue OMF::SFA::AM::AMManagerException => aex
|
133
|
-
return RackException.new(400, aex.to_s).reply
|
136
|
+
# rescue OMF::SFA::AM::AMManagerException => aex
|
137
|
+
# return RackException.new(400, aex.to_s).reply
|
134
138
|
rescue Exception => ex
|
135
139
|
body = {
|
136
140
|
:error => {
|
@@ -140,13 +144,7 @@ module OMF::SFA::AM::Rest
|
|
140
144
|
}
|
141
145
|
warn "ERROR: #{ex}"
|
142
146
|
debug ex.backtrace.join("\n")
|
143
|
-
|
144
|
-
# doc = root.document
|
145
|
-
# reason = root.add_child(Nokogiri::XML::Element.new('reason', doc))
|
146
|
-
# reason.content = ex.to_s
|
147
|
-
# reason = root.add_child(Nokogiri::XML::Element.new('bt', doc))
|
148
|
-
# reason.content = ex.backtrace.join("\n\t")
|
149
|
-
return [500, {"Content-Type" => 'application/json'}, body]
|
147
|
+
return [500, { "Content-Type" => 'application/json', 'Access-Control-Allow-Origin' => '*', 'Access-Control-Allow-Methods' => 'GET, POST, OPTIONS' }, JSON.pretty_generate(body)]
|
150
148
|
end
|
151
149
|
end
|
152
150
|
|
@@ -163,15 +161,15 @@ module OMF::SFA::AM::Rest
|
|
163
161
|
def on_post(resource_uri, opts)
|
164
162
|
#debug 'POST: resource_uri "', resource_uri, '" - ', opts.inspect
|
165
163
|
description, format = parse_body(opts, [:json, :form])
|
166
|
-
debug 'POST(', resource_uri, '): body(', format, '): "', description, '"'
|
164
|
+
#debug 'POST(', resource_uri, '): body(', format, '): "', description, '"'
|
167
165
|
|
168
166
|
if resource = opts[:resource]
|
169
167
|
debug 'POST: Modify ', resource
|
170
168
|
modify_resource(resource, description, opts)
|
171
169
|
else
|
172
|
-
debug 'POST: Create? ', description.class
|
173
170
|
if description.is_a? Array
|
174
171
|
resources = description.map do |d|
|
172
|
+
debug 'POST: Create? ', d
|
175
173
|
create_resource(d, opts)
|
176
174
|
end
|
177
175
|
return show_resources(resources, nil, opts)
|
@@ -253,7 +251,7 @@ module OMF::SFA::AM::Rest
|
|
253
251
|
|
254
252
|
|
255
253
|
def create_resource(description, opts, resource_uri = nil)
|
256
|
-
debug "Create: #{description.class}--#{description}"
|
254
|
+
#debug "Create: #{description.class}--#{description}"
|
257
255
|
|
258
256
|
if resource_uri
|
259
257
|
if UUID.validate(resource_uri)
|
@@ -272,7 +270,7 @@ module OMF::SFA::AM::Rest
|
|
272
270
|
modify_resource(resource, description, opts)
|
273
271
|
else
|
274
272
|
resource = @resource_class.create(description)
|
275
|
-
|
273
|
+
on_new_resource(resource)
|
276
274
|
end
|
277
275
|
if (context = opts[:context])
|
278
276
|
add_resource_to_context(resource, context)
|
@@ -280,6 +278,13 @@ module OMF::SFA::AM::Rest
|
|
280
278
|
return resource
|
281
279
|
end
|
282
280
|
|
281
|
+
# Can be used to further customize a newly created
|
282
|
+
# resource.
|
283
|
+
#
|
284
|
+
def on_new_resource(resource)
|
285
|
+
debug "Created: #{resource}"
|
286
|
+
end
|
287
|
+
|
283
288
|
def add_resource_to_context(user, context)
|
284
289
|
raise UnsupportedMethodException.new
|
285
290
|
end
|
@@ -312,7 +317,7 @@ module OMF::SFA::AM::Rest
|
|
312
317
|
raise UnsupportedBodyFormatException.new('Send body raw, not as form data')
|
313
318
|
end
|
314
319
|
(body = body.string) if body.is_a? StringIO
|
315
|
-
debug 'PARSE_BODY(ct: ', req.content_type, '): ', body.inspect
|
320
|
+
#debug 'PARSE_BODY(ct: ', req.content_type, '): ', body.inspect
|
316
321
|
unless content_type = req.content_type
|
317
322
|
body.strip!
|
318
323
|
if ['/', '{', '['].include?(body[0])
|
@@ -387,7 +392,6 @@ module OMF::SFA::AM::Rest
|
|
387
392
|
#:about => about,
|
388
393
|
:type => resource.resource_type,
|
389
394
|
}.merge!(props)
|
390
|
-
#res = {"#{resource.resource_type}_response" => res}
|
391
395
|
else
|
392
396
|
res = {:error => 'Unknown resource'}
|
393
397
|
end
|
@@ -487,11 +491,12 @@ module OMF::SFA::AM::Rest
|
|
487
491
|
# * :result - hash or array describing the result (may used by JS to further format)
|
488
492
|
#
|
489
493
|
def render_html(parts = {})
|
494
|
+
#puts "PP>> #{parts}"
|
490
495
|
tmpl = html_template()
|
491
496
|
if (result = parts[:result])
|
492
497
|
tmpl = tmpl.gsub('##JS##', JSON.pretty_generate(result))
|
493
498
|
end
|
494
|
-
title = parts[:title] || @@service_name
|
499
|
+
title = parts[:title] || @@service_name || "Unknown Service"
|
495
500
|
tmpl = tmpl.gsub('##TITLE##', title)
|
496
501
|
if (service = parts[:service])
|
497
502
|
tmpl = tmpl.gsub('##SERVICE##', service)
|
@@ -512,22 +517,16 @@ module OMF::SFA::AM::Rest
|
|
512
517
|
level: 0,
|
513
518
|
href_prefix: "#{req.path}/"
|
514
519
|
}.merge(opts)
|
515
|
-
#tmpl = html_template()
|
516
|
-
#tmpl = tmpl.gsub('##JS##', JSON.pretty_generate(body))
|
517
520
|
|
518
|
-
#h1 = "<h1>#{@@service_name || env["HTTP_HOST"]}</h1>"
|
519
|
-
#tmpl = tmpl.gsub('##TITLE##', @@service_name || env["HTTP_HOST"])
|
520
521
|
path = req.path.split('/').select { |p| !p.empty? }
|
521
522
|
h2 = ["<a href='/?_format=html&_level=0'>ROOT</a>"]
|
522
523
|
path.each_with_index do |s, i|
|
523
524
|
h2 << "<a href='/#{path[0 .. i].join('/')}?_format=html&_level=#{i % 2 ? 0 : 1}'>#{s}</a>"
|
524
525
|
end
|
525
|
-
#tmpl = tmpl.gsub('##SERVICE##', h2.join('/'))
|
526
526
|
|
527
527
|
res = []
|
528
528
|
_convert_obj_to_html(body, nil, res, opts)
|
529
529
|
|
530
|
-
#tmpl.gsub('##CONTENT##', res.join("\n"))
|
531
530
|
render_html(
|
532
531
|
result: body,
|
533
532
|
title: @@service_name || env["HTTP_HOST"],
|
@@ -543,8 +542,8 @@ module OMF::SFA::AM::Rest
|
|
543
542
|
protected
|
544
543
|
def _convert_obj_to_html(obj, ref_name, res, opts)
|
545
544
|
klass = obj.class
|
546
|
-
#puts ">>>> #{obj.class}::#{obj}"
|
547
|
-
if obj.is_a? Array
|
545
|
+
#puts "CONVERT>>>> #{obj.class}::#{obj}"
|
546
|
+
if (obj.is_a? OMF::SFA::Resource::OPropertyArray) || obj.is_a?(Array)
|
548
547
|
if obj.empty?
|
549
548
|
res << '<span class="empty">empty</span>'
|
550
549
|
else
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'omf-sfa/resource/oresource'
|
2
2
|
require 'json'
|
3
3
|
require 'time'
|
4
|
+
require 'omf_base/lobject'
|
4
5
|
|
5
6
|
# We use the JSON serialization for Time objecs from 'json/add/core' in order to avoid
|
6
7
|
# the conflicts with the 'active_support/core_ext' which is included in 'omf_base'
|
@@ -28,113 +29,200 @@ class Time
|
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
31
|
-
raise "JSON deserialisation no longer working - require 'json' early" unless JSON.load(Time.now.to_json).is_a? Time
|
32
|
+
#raise "JSON deserialisation no longer working - require 'json' early" unless JSON.load(Time.now.to_json).is_a? Time
|
32
33
|
|
33
34
|
module OMF::SFA::Resource
|
34
35
|
|
35
36
|
# Each resource will have a few properties.
|
36
37
|
#
|
37
38
|
#
|
38
|
-
class OProperty
|
39
|
+
class OProperty < OMF::Base::LObject
|
39
40
|
include DataMapper::Resource
|
40
41
|
property :id, Serial
|
41
42
|
|
42
43
|
property :name, String
|
43
|
-
property :
|
44
|
+
property :type, String, length: 2
|
45
|
+
property :s_value, String # actually serialized Object
|
46
|
+
property :n_value, Float
|
44
47
|
|
45
48
|
belongs_to :o_resource
|
46
49
|
|
47
|
-
module ArrayProxy
|
48
|
-
def << (val)
|
49
|
-
if @on_set_block
|
50
|
-
val = @on_set_block.call(val)
|
51
|
-
return if val.nil?
|
52
|
-
end
|
53
|
-
@oproperty << val
|
54
|
-
@on_modified_block.call(val, true) if @on_add_block
|
55
|
-
super
|
56
|
-
end
|
57
|
-
|
58
|
-
def clear()
|
59
|
-
_remove { super }
|
60
|
-
end
|
61
|
-
|
62
|
-
def delete(obj)
|
63
|
-
_remove { super }
|
64
|
-
end
|
50
|
+
# module ArrayProxy
|
51
|
+
# def << (val)
|
52
|
+
# if @on_set_block
|
53
|
+
# val = @on_set_block.call(val)
|
54
|
+
# return if val.nil?
|
55
|
+
# end
|
56
|
+
# @oproperty << val
|
57
|
+
# @on_modified_block.call(val, true) if @on_add_block
|
58
|
+
# super
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# def clear()
|
62
|
+
# _remove { super }
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# def delete(obj)
|
66
|
+
# _remove { super }
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# def delete_at(index)
|
70
|
+
# _remove { super }
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# def delete_if(&block)
|
74
|
+
# _remove { super }
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# # Callback to support 'reverse' operation
|
78
|
+
# def on_modified(&block)
|
79
|
+
# @on_modified_block = block
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# def on_set(&block)
|
83
|
+
# @on_set_block = block
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# private
|
87
|
+
# def _remove(&block)
|
88
|
+
# old = self.dup
|
89
|
+
# r = block.call()
|
90
|
+
# removed = old - self
|
91
|
+
# unless removed.empty?
|
92
|
+
# if @on_remove_block
|
93
|
+
# removed.each {|it| @on_modified_block.call(it, false) }
|
94
|
+
# end
|
95
|
+
# @oproperty.value = self
|
96
|
+
# end
|
97
|
+
# r
|
98
|
+
# end
|
99
|
+
# end
|
65
100
|
|
66
|
-
|
67
|
-
|
101
|
+
def self.prop_all(query, resource_class = nil)
|
102
|
+
i = 0
|
103
|
+
where = query.map do |pn, v|
|
104
|
+
h = _analyse_value(v)
|
105
|
+
tbl = "p#{i}"
|
106
|
+
i += 1
|
107
|
+
if (val = h[:v]).is_a? String
|
108
|
+
val = "'#{val}'"
|
109
|
+
end
|
110
|
+
"#{tbl}.#{h[:f]} #{h[:t] == 's' ? 'LIKE' : '='} #{val}"
|
68
111
|
end
|
69
|
-
|
70
|
-
|
71
|
-
_remove { super }
|
112
|
+
i.times do |j|
|
113
|
+
where << "r.id = p#{j}.o_resource_id"
|
72
114
|
end
|
115
|
+
where << "r.type = '#{resource_class}'" if resource_class
|
73
116
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
117
|
+
table = storage_names[:default]
|
118
|
+
from = i.times.map {|j| "#{table} AS p#{j}" }
|
119
|
+
from << "omf_sfa_resource_o_resources AS r" # TODO: Shouldn't hard-code that
|
120
|
+
q = "SELECT r.id, r.type, r.uuid, r.name FROM #{from.join(', ')} WHERE #{where.join(' AND ')};"
|
121
|
+
debug "prop_all q: #{q}"
|
122
|
+
res = repository(:default).adapter.select(q)
|
123
|
+
puts OMF::JobService::Resource::Job
|
78
124
|
|
79
|
-
|
80
|
-
|
125
|
+
ores = res.map do |qr|
|
126
|
+
if resource_class
|
127
|
+
resource_class.first(id: qr.id, uuid: qr.uuid, name: qr.name) # TODO: Does this create a DB call?
|
128
|
+
else
|
129
|
+
_create_resource(qr)
|
130
|
+
end
|
81
131
|
end
|
132
|
+
#puts "RES>>> #{ores}"
|
133
|
+
ores
|
134
|
+
end
|
82
135
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
136
|
+
@@name2class = {}
|
137
|
+
def self._create_resource(query_result)
|
138
|
+
qr = query_result
|
139
|
+
unless klass = @@name2class[qr.type]
|
140
|
+
begin
|
141
|
+
klass = qr.type.split('::').inject(Object) do |mod, class_name|
|
142
|
+
mod.const_get(class_name)
|
143
|
+
end
|
144
|
+
rescue Exception => ex
|
145
|
+
warn "Can't find class '#{qr.type}' for resource - #{ex}"
|
146
|
+
return nil
|
93
147
|
end
|
94
|
-
|
148
|
+
@@name2class[qr.type] = klass
|
95
149
|
end
|
150
|
+
klass.first(id: qr.id, uuid: qr.uuid, name: qr.name) # TODO: Does this create a DB call?
|
96
151
|
end
|
97
152
|
|
98
153
|
def value=(val)
|
99
|
-
|
154
|
+
h = self.class._analyse_value(val)
|
155
|
+
attribute_set(h[:f], h[:v])
|
156
|
+
attribute_set(:type, h[:t])
|
100
157
|
save
|
101
158
|
end
|
102
159
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
160
|
+
# if val.is_a? Numeric
|
161
|
+
# attribute_set(:n_value, val)
|
162
|
+
# attribute_set(:type, (val.is_a? Integer) ? 'i' : 'f')
|
163
|
+
# elsif val.is_a? String
|
164
|
+
# attribute_set(:s_value, val)
|
165
|
+
# attribute_set(:type, 's')
|
166
|
+
# elsif val.is_a? OResource
|
167
|
+
# attribute_set(:s_value, val.uuid.to_s)
|
168
|
+
# attribute_set(:type, 'r')
|
169
|
+
# elsif val.is_a? Time
|
170
|
+
# attribute_set(:n_value, val.to_i)
|
171
|
+
# attribute_set(:type, 't')
|
172
|
+
# else
|
173
|
+
# puts "OOOOO INSETRT (#{attribute_get(:name)})> #{val.class}"
|
174
|
+
# attribute_set(:s_value, JSON.generate([val]))
|
175
|
+
# attribute_set(:type, 'o')
|
176
|
+
# end
|
177
|
+
# save
|
178
|
+
# end
|
179
|
+
|
180
|
+
def self._analyse_value(val)
|
181
|
+
|
182
|
+
if val.is_a? Numeric
|
183
|
+
return {v: val, t: ((val.is_a? Integer) ? 'i' : 'f'), f: :n_value}
|
184
|
+
elsif val.is_a? String
|
185
|
+
return {v: val, t: 's', f: :s_value}
|
186
|
+
elsif val.is_a? Symbol
|
187
|
+
return {v: val.to_s, t: 's', f: :s_value}
|
188
|
+
elsif val.is_a? OResource
|
189
|
+
return {v: val.uuid.to_s, t: 'r', f: :s_value}
|
190
|
+
elsif val.is_a? Time
|
191
|
+
return {v: val.to_i, t: 'r', f: :n_value}
|
192
|
+
else
|
193
|
+
#debug "SETTING VALUE> Class: #{val.class}"
|
194
|
+
return {v: JSON.generate([val]), t: 'o', f: :s_value}
|
110
195
|
end
|
111
|
-
val
|
112
196
|
end
|
113
197
|
|
114
|
-
def
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
198
|
+
def value()
|
199
|
+
case type = attribute_get(:type)
|
200
|
+
when 'i'
|
201
|
+
val = attribute_get(:n_value).to_i
|
202
|
+
when 'f'
|
203
|
+
val = attribute_get(:n_value)
|
204
|
+
when 's'
|
205
|
+
val = attribute_get(:s_value)
|
206
|
+
when 'r'
|
207
|
+
uuid = attribute_get(:s_value)
|
208
|
+
val = OResource.first(uuid: uuid)
|
209
|
+
when 't'
|
210
|
+
val = Time.at(attribute_get(:n_value))
|
211
|
+
when 'o'
|
212
|
+
js = attribute_get(:s_value)
|
213
|
+
#debug "GET VALUE> <#{js}>"
|
214
|
+
# http://www.ruby-lang.org/en/news/2013/02/22/json-dos-cve-2013-0269/
|
215
|
+
val = JSON.load(js)[0]
|
216
|
+
#puts "VALUE: #{js.inspect}-#{val.inspect}-#{val.class}"
|
217
|
+
if val.kind_of? Array
|
218
|
+
val.tap {|v| v.extend(ArrayProxy).instance_variable_set(:@oproperty, self) }
|
219
|
+
end
|
220
|
+
else
|
221
|
+
throw "Unknown property type '#{type}'"
|
222
|
+
end
|
223
|
+
return val
|
120
224
|
end
|
121
225
|
|
122
|
-
#def value()
|
123
|
-
# #puts "VALUE() @value_:'#{@value_.inspect}'"
|
124
|
-
# unless @value_
|
125
|
-
# js = attribute_get(:value)
|
126
|
-
# puts "JS #{js.inspect}"
|
127
|
-
# if js
|
128
|
-
# @value_ = JSON.parse(js)[0]
|
129
|
-
# if @value_.kind_of? Array
|
130
|
-
# @old_value_ = @value_.dup
|
131
|
-
# end
|
132
|
-
# end
|
133
|
-
# end
|
134
|
-
# #puts "VALUE()2 @value_:'#{@value_.inspect}'"
|
135
|
-
# @value_
|
136
|
-
#end
|
137
|
-
|
138
226
|
def valid?(context = :default)
|
139
227
|
self.name != nil #&& self.value != nil
|
140
228
|
end
|
@@ -156,6 +244,14 @@ module OMF::SFA::Resource
|
|
156
244
|
false
|
157
245
|
end
|
158
246
|
|
247
|
+
def to_hash
|
248
|
+
{name: self.name, value: self.value}
|
249
|
+
end
|
250
|
+
|
251
|
+
def to_json(*args)
|
252
|
+
to_hash.to_json(*args)
|
253
|
+
end
|
254
|
+
|
159
255
|
def to_s()
|
160
256
|
super() + " - name: #{self.name} value: #{self.value}"
|
161
257
|
end
|
@@ -175,4 +271,62 @@ module OMF::SFA::Resource
|
|
175
271
|
|
176
272
|
end # OProperty
|
177
273
|
|
274
|
+
class OPropertyArray
|
275
|
+
def <<(val)
|
276
|
+
p = OProperty.create(name: @name, o_resource: @resource)
|
277
|
+
p.value = val
|
278
|
+
@on_set_block.call(val) if @on_set_block
|
279
|
+
self
|
280
|
+
end
|
281
|
+
|
282
|
+
# Delete all members
|
283
|
+
def clear
|
284
|
+
OProperty.all(name: @name, o_resource: @resource).destroy
|
285
|
+
self
|
286
|
+
end
|
287
|
+
|
288
|
+
[:each, :each_with_index, :select, :map].each do |n|
|
289
|
+
define_method n do |&block|
|
290
|
+
c = OProperty.all(name: @name, o_resource: @resource)
|
291
|
+
e = Enumerator.new do |y|
|
292
|
+
if prop = c.first
|
293
|
+
val = prop.value
|
294
|
+
val = @on_set_block.call(val) if @on_set_block
|
295
|
+
y << val
|
296
|
+
end
|
297
|
+
end
|
298
|
+
e.send(n, &block)
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
def empty?
|
303
|
+
OProperty.count(name: @name, o_resource: @resource) == 0
|
304
|
+
end
|
305
|
+
|
306
|
+
# Callback to support 'reverse' operation
|
307
|
+
def on_modified(&block)
|
308
|
+
raise "Not implemented"
|
309
|
+
#@on_modified_block = block
|
310
|
+
end
|
311
|
+
|
312
|
+
def on_set(&block)
|
313
|
+
@on_set_block = block
|
314
|
+
end
|
315
|
+
|
316
|
+
def to_json(*args)
|
317
|
+
OProperty.all(name: @name, o_resource: @resource).map do |p|
|
318
|
+
p.value
|
319
|
+
end.to_json(*args)
|
320
|
+
end
|
321
|
+
|
322
|
+
def to_s
|
323
|
+
"<#{self.class}: name=#{@name} resource=#{@resource.name || @resource.uuid} >"
|
324
|
+
end
|
325
|
+
|
326
|
+
def initialize(resource, name)
|
327
|
+
@resource = resource
|
328
|
+
@name = name
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
178
332
|
end # OMF::SFA::Resource
|
@@ -83,7 +83,7 @@ module OMF::SFA::Resource
|
|
83
83
|
op[pname] = opts
|
84
84
|
|
85
85
|
define_method pname do
|
86
|
-
res =
|
86
|
+
res = oproperty_array_get(pname)
|
87
87
|
if res == nil
|
88
88
|
oproperty_set(pname, [])
|
89
89
|
# We make a oproperty_get in order to get the extended Array with
|
@@ -118,14 +118,16 @@ module OMF::SFA::Resource
|
|
118
118
|
# helps other entities to learn if this property is functional or not.
|
119
119
|
#
|
120
120
|
define_method "#{pname}_add" do |v|
|
121
|
-
|
121
|
+
oproperty_array_get(pname) << v
|
122
|
+
#self.send(pname.to_sym) << v
|
122
123
|
end
|
123
124
|
|
124
125
|
define_method "#{pname}=" do |v|
|
125
126
|
unless v.is_a? Array
|
126
127
|
raise "Property '#{pname}' in '#{self.class}' requires an Array in setter - #{v.inspect}"
|
127
128
|
end
|
128
|
-
res = self.send(pname.to_sym)
|
129
|
+
#res = self.send(pname.to_sym)
|
130
|
+
res = oproperty_array_get(pname)
|
129
131
|
res.clear # clear any old values
|
130
132
|
v.each {|it| res << it }
|
131
133
|
res
|
@@ -168,6 +170,10 @@ module OMF::SFA::Resource
|
|
168
170
|
end
|
169
171
|
end
|
170
172
|
|
173
|
+
def self.prop_all(query)
|
174
|
+
OProperty.prop_all(query, self)
|
175
|
+
end
|
176
|
+
|
171
177
|
# Clone this resource this resource. However, the clone will have a unique UUID
|
172
178
|
#
|
173
179
|
def clone()
|
@@ -259,6 +265,11 @@ module OMF::SFA::Resource
|
|
259
265
|
end
|
260
266
|
alias_method :[]=, :oproperty_set
|
261
267
|
|
268
|
+
def oproperty_array_get(pname)
|
269
|
+
pname = pname.to_sym
|
270
|
+
ap = (@array_properties ||= {})[pname] ||= OPropertyArray.new(self, pname)
|
271
|
+
end
|
272
|
+
|
262
273
|
def oproperties_as_hash
|
263
274
|
res = {}
|
264
275
|
oproperties.each do |p|
|
@@ -360,23 +371,26 @@ module OMF::SFA::Resource
|
|
360
371
|
end
|
361
372
|
|
362
373
|
def to_json(*a)
|
363
|
-
|
364
|
-
# need an id, means I haven't been saved yet
|
365
|
-
save
|
366
|
-
end
|
367
|
-
{
|
368
|
-
'json_class' => self.class.name,
|
369
|
-
'id' => self.id
|
370
|
-
}.to_json(*a)
|
371
|
-
end
|
374
|
+
to_hash_brief().to_json(*a)
|
372
375
|
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
376
|
+
# unless self.id
|
377
|
+
# # need an id, means I haven't been saved yet
|
378
|
+
# save
|
379
|
+
# end
|
380
|
+
# {
|
381
|
+
# 'json_class' => self.class.name,
|
382
|
+
# 'id' => self.id
|
383
|
+
# }.to_json(*a)
|
378
384
|
end
|
379
385
|
|
386
|
+
# def as_json(options = { })
|
387
|
+
# raise "DO WE STILL NEED THIS"
|
388
|
+
# {
|
389
|
+
# "json_class" => self.class.name,
|
390
|
+
# "id" => self.id
|
391
|
+
# }
|
392
|
+
# end
|
393
|
+
|
380
394
|
|
381
395
|
#def self.from_json(o)
|
382
396
|
# puts "FROM_JSON"
|
data/lib/omf-sfa/version.rb
CHANGED
data/omf_sfa.gemspec
CHANGED
@@ -40,7 +40,8 @@ Gem::Specification.new do |s|
|
|
40
40
|
s.add_runtime_dependency "rack-rpc", "~> 0.0.6"
|
41
41
|
s.add_runtime_dependency "data_mapper", "~> 1.2.0"
|
42
42
|
s.add_runtime_dependency "bluecloth", "~> 2.2.0"
|
43
|
-
s.add_runtime_dependency "omf_common", "~> 6.0.0"
|
43
|
+
#s.add_runtime_dependency "omf_common", "~> 6.0.0"
|
44
|
+
#s.add_runtime_dependency "omf_base", "~> 6.0.0"
|
44
45
|
s.add_runtime_dependency "eventmachine", "~> 1.0.3"
|
45
46
|
s.add_runtime_dependency "em-minitest-spec", "~> 1.1.1"
|
46
47
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: omf_sfa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-02-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: minitest
|
@@ -331,22 +331,6 @@ dependencies:
|
|
331
331
|
- - ~>
|
332
332
|
- !ruby/object:Gem::Version
|
333
333
|
version: 2.2.0
|
334
|
-
- !ruby/object:Gem::Dependency
|
335
|
-
name: omf_common
|
336
|
-
requirement: !ruby/object:Gem::Requirement
|
337
|
-
none: false
|
338
|
-
requirements:
|
339
|
-
- - ~>
|
340
|
-
- !ruby/object:Gem::Version
|
341
|
-
version: 6.0.0
|
342
|
-
type: :runtime
|
343
|
-
prerelease: false
|
344
|
-
version_requirements: !ruby/object:Gem::Requirement
|
345
|
-
none: false
|
346
|
-
requirements:
|
347
|
-
- - ~>
|
348
|
-
- !ruby/object:Gem::Version
|
349
|
-
version: 6.0.0
|
350
334
|
- !ruby/object:Gem::Dependency
|
351
335
|
name: eventmachine
|
352
336
|
requirement: !ruby/object:Gem::Requirement
|