omf_sfa 0.1.4 → 0.1.5
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/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
|