riddl 0.99.218 → 0.99.219

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e2ea540548ddd792ec444fec0648dc10c0ed8cfb
4
- data.tar.gz: 72eb21e4bc237319f5734f4247760404c11279f0
3
+ metadata.gz: f5a7fd98e32be12a9b153657c3959ac670be0e3f
4
+ data.tar.gz: d743380ae7ebab04a1c4d8ddcdb1d3acfdb156c9
5
5
  SHA512:
6
- metadata.gz: 1fdc06a909c934f12169de63e9c30d0182c971daebe3ff42b1eb8be8d90ea4dc6b3780b7db663a92e7947f23864b40c5ce3857ae2c58d41353fa44eb79a5d3ec
7
- data.tar.gz: 58b256db07facc0bafa349b8c004fa89ee2a89d87112665cdfe4cb80cc79508a2d5eb0c6dbd273f752062760541df1f216165a20c9aa27266152f5176b091f20
6
+ metadata.gz: a1e1424f7bb9820af80dbfe314071f8a9f81584eb7ee13579c5571e0bcb63909a506f6c5ed12f9d78372bc1e8233dc5ce7f37fce2b273801faf029f2557ffc86
7
+ data.tar.gz: 454f78db0320ad93dece4b885ec3796ae267f40cad9f3061d5fe9676658a983624bb49d93e28ad05b7f5b9bc1acf9fc20bbd74bbd3a9054825ea8957992db0f3
@@ -0,0 +1,33 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../client')
2
+
3
+ module Riddl
4
+ module Utils
5
+ module Description
6
+
7
+ class RDR < Riddl::Implementation
8
+ def response
9
+ @headers << Riddl::Header.new("RIDDL_DESCRIPTION", 'oh my, a riddl description')
10
+ return Riddl::Parameter::Complex.new("riddl-description","text/xml",@a[0])
11
+ end
12
+ end
13
+
14
+ class Call < Riddl::Implementation
15
+ def response
16
+ client = Riddl::Client.new @a[3]
17
+
18
+ path = client.resource "/" + @a[4]
19
+ @status, result, headers = if @a[0].nil?
20
+ path.request @m => [ Riddl::Header.new("RIDDL_DECLARATION_RESOURCE", @a[2]), Riddl::Header.new("RIDDL-DECLARATION-PATH", @a[1]) ] + @h.map{|a,b| Riddl::Header.new(a,b)} + @p
21
+ else
22
+ path.request @m => [ Riddl::Header.new("RIDDL_DECLARATION_RESOURCE", @a[2]), Riddl::Header.new("RIDDL-DECLARATION-PATH", @a[1]) ] + @a[0].headers.map{|a,b| Riddl::Header.new(a,b)} + @a[0].response
23
+ end
24
+ headers.each do |k,v|
25
+ @headers << Riddl::Header.new(k,v) unless ["CONTENT_TYPE", "CONTENT_DISPOSITION", "RIDDL_TYPE", "CONTENT_ID", "CONTENT_LENGTH", "CONNECTION", "SERVER"].include?(k)
26
+ end
27
+ result
28
+ end
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,255 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8"/>
5
+ <meta http-equiv="X-UA-Compatible" content="IE=EDGE"/>
6
+
7
+ <title>Documentation</title>
8
+
9
+ <style>
10
+ body {
11
+ counter-reset: h1counter;
12
+ }
13
+ h1 { font-size: 1.5em; counter-reset: h2counter; }
14
+ h2 { font-size: 1.2em; }
15
+ h3 { font-size: 1.0em }
16
+ h1:before {
17
+ content: counter(h1counter) ".\0000a0\0000a0";
18
+ counter-increment: h1counter;
19
+ }
20
+ h2:before {
21
+ content: counter(h1counter) "." counter(h2counter) ".\0000a0\0000a0";
22
+ counter-increment: h2counter;
23
+ }
24
+ .code {
25
+ border: 1px dashed #425d73; background-color: #DEE6EE; margin:0px; padding: 0.5em 1em; font-family: monospace; font-size:0.9em;
26
+ }
27
+ </style>
28
+
29
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
30
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.5.0/lodash.min.js"></script>
31
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.2/marked.min.js"></script>
32
+ <script src="https://cdn.rawgit.com/vkiryukhin/vkBeautify/master/vkbeautify.js"></script>
33
+ <script>//<![CDATA[
34
+ $.fn.serializeXML = function(){
35
+ var out = '';
36
+ if (typeof XMLSerializer == 'function') {
37
+ var xs = new XMLSerializer();
38
+ this.each(function() {
39
+ out += xs.serializeToString(this);
40
+ });
41
+ } else if (this[0] && this[0].xml != 'undefined') {
42
+ this.each(function() {
43
+ out += this.xml;
44
+ });
45
+ }
46
+ return out;
47
+ };
48
+
49
+ function docChildren(path,name,data){
50
+ var ret= [];
51
+ var subject = path ? $(path,data) : $(data);
52
+ subject.children().each(function(k,ele){
53
+ if (ele.localName == name && ele.namespaceURI == "http://riddl.org/ns/documentation/1.0") {
54
+ ret.push(ele);
55
+ }
56
+ });
57
+ return $(ret);
58
+ }
59
+
60
+ function codeFormat(temp) {
61
+ temp = temp.replace(/\&/g,"&amp;").replace(/\"/g,"&quot;").replace(/>/g,"&gt;").replace(/</g,"&lt;").replace(/'/g,"&apos;");
62
+ temp = temp.replace(/\t/g,' ');
63
+ temp = temp.replace(/\r/g,'');
64
+ temp = temp.replace(/^$/g,' ');
65
+ temp = temp.replace(/^ */gm,function mf(m){
66
+ var tm = (m.length + 2) * 0.6 + 2 * 0.6;
67
+ return "<div style='text-indent:-" + tm + "em;margin-left:" + tm + "em'>" + (Array(m.length + 1).join("&#160;"));
68
+ });
69
+ temp = temp.replace(/ /g," &#160;");
70
+ temp = temp.replace(/\n/g,"</div>\n");
71
+ temp += "</div>\n";
72
+ temp = temp.replace(/href=&quot;([^&]+)&quot;/g,'href=&quot;<a href="/__doc_includes/$1">$1</a>&quot;')
73
+ return temp;
74
+ }
75
+
76
+ $(document).ready(function(){
77
+ var rpath = "<%= @h['RIDDL_DECLARATION_PATH'] %>";
78
+ var pathele = _.compact(rpath.split('/'));
79
+
80
+ var t = $('#breadcrumblink')[0];
81
+ var link = "";
82
+ _.each(pathele,function(e){
83
+ link = link + "/" + e;
84
+ var clone = document.importNode(t.content, true);
85
+ $('a',clone).attr('href',link + "/?doc=true");
86
+ $('a',clone).text(e);
87
+ $('#breadcrumb').append(clone);
88
+ });
89
+
90
+ $.ajax({
91
+ url: rpath + "?riddl-resource-description",
92
+ success: function(data){
93
+ $('#main').append(marked(docChildren('description > resource','documentation',data).text()));
94
+
95
+ var subr = $('description > resource > resource',data);
96
+ if (subr.length == 0) {
97
+ $('#subresources').remove();
98
+ } else {
99
+ $('description > resource > resource',data).each(function(k,ele){
100
+ var sum = docChildren(null,'documentation',ele).attr('summary');
101
+ var exa = docChildren(null,'example',ele);
102
+ exa = exa.length == 0 ? null : exa.text();
103
+ if (exa) {
104
+ var rell = exa;
105
+ if ($(ele).attr('relative')) {
106
+ var relt = exa + ' (' + $(ele).attr('relative') + ')';
107
+ } else {
108
+ var relt = '{} (any string possible)';
109
+ }
110
+ } else {
111
+ var rell = $(ele).attr('relative');
112
+ var relt = _.trim(rell);
113
+ }
114
+ var t = $('#subresourceitem')[0];
115
+ var clone = document.importNode(t.content, true);
116
+ $('a',clone).attr('href','./' + rell + '/?doc=true');
117
+ if (relt != "") {
118
+ $('a',clone).text(relt);
119
+ }
120
+ if (sum) { $('.content',clone).text(sum); }
121
+ $('#subresources .anchor').append(clone);
122
+ });
123
+ }
124
+
125
+ var oprs = $('description > resource > get, description > resource > post, description > resource > put, description > resource > delete, description > resource > request',data);
126
+ if (oprs.length == 0) {
127
+ $('#operations').remove();
128
+ } else {
129
+ oprs.each(function(k,ele){
130
+ var sum = docChildren(null,'documentation',ele).attr('summary');
131
+ var details = docChildren(null,'documentation',ele).text();
132
+ var example = docChildren(null,'example',ele);
133
+ var ex = null;
134
+
135
+ var tin = $(ele).attr('in');
136
+ var tout = $(ele).attr('out');
137
+ var whatl = $(ele).prop('tagName');
138
+ var whatd = tin == "*" ? '' : '( ' + tin + ' )';
139
+ whatd += tout ? ' : ' + tout : '';
140
+
141
+ var tinmess = "";
142
+ if (tin && tin != "*") {
143
+ $('description > message[name="' + tin + '"]',data).each(function(k,mess){
144
+ tinmess = mess;
145
+ _.each(mess.attributes,function(attr){
146
+ if (attr.localName == 'example' && attr.namespaceURI == "http://riddl.org/ns/documentation/1.0") {
147
+ ex = attr.nodeValue;
148
+ }
149
+ });
150
+ });
151
+ }
152
+ if (example.length > 0) { ex = example.text(); }
153
+
154
+ var toutmess = "";
155
+ if (tout && tout != "*") {
156
+ $('description > message[name="' + tout + '"]',data).each(function(k,mess){
157
+ toutmess = mess;
158
+ });
159
+ }
160
+
161
+ // Overview
162
+ var t = $('#operationitem')[0];
163
+ var clone = document.importNode(t.content, true);
164
+ $('.what .link',clone).text(whatl);
165
+ $('.what .link',clone).attr('href','#' + (whatl + '_' + whatd).replace(/ /g,'_'));
166
+ $('.what .details',clone).text(whatd);
167
+ if (ex != null) {
168
+ if (ex == "")
169
+ $('.what .try a',clone).attr('href',window.location.pathname);
170
+ else
171
+ $('.what .try a',clone).attr('href','?' + ex);
172
+ } else {
173
+ $('.what .try',clone).remove();
174
+ }
175
+ if (sum) { $('.content',clone).text(sum); }
176
+ $('#operations .anchor').append(clone);
177
+
178
+ //Details
179
+ var t = $('#operationsec')[0];
180
+ var clone = document.importNode(t.content, true);
181
+ $('.what',clone).text(whatl + ' ' + whatd);
182
+ $('.what',clone).attr('id',(whatl + '_' + whatd).replace(/ /g,'_'));
183
+ if (_.trim(details) == "") {
184
+ $('.text',clone).text(sum);
185
+ } else {
186
+ $('.text',clone).append(marked(details));
187
+ }
188
+ if (ex != null) {
189
+ if (ex == "") {
190
+ $('.try a',clone).attr('href',window.location.pathname);
191
+ } else {
192
+ $('.try a',clone).attr('href','?' + ex);
193
+ $('.try a',clone).text('?' + ex);
194
+ }
195
+ } else {
196
+ $('.try',clone).remove();
197
+ }
198
+
199
+ if (tin && tin != "*") {
200
+ $('.input .message',clone).html(codeFormat(vkbeautify.xml($(tinmess).serializeXML(),' ')));
201
+ } else {
202
+ $('.input',clone).remove();
203
+ }
204
+ if (tout) {
205
+ $('.output .message',clone).html(codeFormat(vkbeautify.xml($(toutmess).serializeXML(),' ')));
206
+ } else {
207
+ $('.output',clone).remove();
208
+ }
209
+ $('#operations').append(clone);
210
+ });
211
+ }
212
+ }
213
+ });
214
+ });
215
+ //]]></script>
216
+ </head>
217
+ <body>
218
+ <template id="breadcrumblink"><span> / </span><a href=""></a></template>
219
+ <template id="subresourceitem"><li><div class='what'><a class='details' href=''>Example missing</a></div><div class="content"></div></li></template>
220
+ <template id="operationitem"><li><div class='what'><a class='link' href=''></a> <span class='details'></span> <span class='try'>(<a href=''>Try it!</a>)</span></div><div class="content"></div></li></template>
221
+ <template id="operationsec">
222
+ <section>
223
+ <h2 class="what" id=""></h2>
224
+ <p class="try">Example: <a href=""><i>no parameters</i></a></p>
225
+ <p class="text"></p>
226
+ <div class="input">
227
+ <h3>Input</h3>
228
+ <div class='message code'></div>
229
+ </div>
230
+ <div class="output">
231
+ <h3>Output</h3>
232
+ <div class='message code'></div>
233
+ </div>
234
+ </section>
235
+ </template>
236
+
237
+ <nav id="breadcrumb">[<a href="/">TOP</a>]</nav>
238
+ <section id="main"></section>
239
+ <section id="subresources">
240
+ <h1>Sub-Resources</h1>
241
+ <p>From here on you can go to the following sub resources:</p>
242
+ <ul class="anchor"></ul>
243
+ </section>
244
+ <section id="operations">
245
+ <h1>Operations</h1>
246
+ <section>
247
+ <p>For this resource the following operations are possible:</p>
248
+ <ul class="anchor"></ul>
249
+ </section>
250
+ </section>
251
+ </body>
252
+ </html>
253
+
254
+
255
+
@@ -0,0 +1,14 @@
1
+ require 'erb'
2
+
3
+ module Riddl
4
+ module Utils
5
+
6
+ class DocOverlay < Riddl::Implementation
7
+ def response
8
+ rval = ERB.new(File.read(File.dirname(__FILE__) + '/docoverlay.html'), 0, "%<>")
9
+ Riddl::Parameter::Complex.new('documentationresponse','text/html',rval.result(binding))
10
+ end
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ require 'mime/types'
2
+ require 'digest/md5'
3
+
4
+ module Riddl
5
+ module Utils
6
+ class Downloadify < Riddl::Implementation
7
+ def response
8
+ mimetype = @p.find{|e|e.name == 'mimetype'}.value
9
+ content = @p.find{|e|e.name == 'content'}.value
10
+ Riddl::Parameter::Complex.new("content",mimetype,content,@r.last)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,24 @@
1
+ require 'mime/types'
2
+ require 'erb'
3
+
4
+ module Riddl
5
+ module Utils
6
+ class ERBServe < Riddl::Implementation
7
+ def response
8
+ path = File.file?(@a[0]) ? @a[0] : "#{@a[0]}/#{@r[@match.length..-1].join('/')}".gsub(/\/+/,'/')
9
+ input = @a[1]
10
+ if File.directory?(path)
11
+ @status = 404
12
+ return []
13
+ end
14
+ if File.exists?(path)
15
+ __ERB_FILE__ = path
16
+ rval = ERB.new(File.read(path), 0, "%<>")
17
+ return Riddl::Parameter::Complex.new("data",MIME::Types.type_for(path)[0].to_s,rval.result(binding))
18
+ end
19
+ @status = 404
20
+ []
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,45 @@
1
+ require 'mime/types'
2
+ require 'charlock_holmes'
3
+ require 'digest/md5'
4
+
5
+ module Riddl
6
+ module Utils
7
+ class FileServe < Riddl::Implementation
8
+ def response
9
+ path = File.file?(@a[0]) ? @a[0] : "#{@a[0]}/#{@r[@match.length-1..-1].join('/')}".gsub(/\/+/,'/')
10
+
11
+ if File.directory?(path)
12
+ @status = 404
13
+ return []
14
+ end
15
+ if File.exists?(path)
16
+ mtime = File.mtime(path)
17
+ @headers << Riddl::Header.new("Last-Modified",mtime.httpdate)
18
+ @headers << Riddl::Header.new("ETag",Digest::MD5.hexdigest(mtime.httpdate))
19
+ htime = @env["HTTP_IF_MODIFIED_SINCE"].nil? ? Time.at(0) : Time.parse(@env["HTTP_IF_MODIFIED_SINCE"])
20
+ if htime == mtime
21
+ @headers << Riddl::Header.new("Connection","close")
22
+ @status = 304 # Not modified
23
+ return []
24
+ else
25
+ fmt = @a[1] || begin
26
+ mt = MIME::Types.type_for(path).first
27
+ if mt.nil?
28
+ 'text/plain;charset=utf-8'
29
+ else
30
+ apx = ''
31
+ if mt.ascii?
32
+ tstr = File.read(path,CharlockHolmes::EncodingDetector::DEFAULT_BINARY_SCAN_LEN)
33
+ apx = ';charset=' + CharlockHolmes::EncodingDetector.detect(tstr)[:encoding]
34
+ end
35
+ mt.to_s + apx
36
+ end
37
+ end
38
+ return Riddl::Parameter::Complex.new('file',fmt,File.open(path,'r'))
39
+ end
40
+ end
41
+ @status = 404
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,328 @@
1
+ module Riddl
2
+ module Utils
3
+ module Notifications
4
+
5
+ module Producer
6
+
7
+ def self::implementation(backend,handler=nil,details=:production)
8
+ unless handler.nil? || (handler.is_a? Riddl::Utils::Notifications::Producer::HandlerBase)
9
+ raise "handler not a subclass of HandlerBase"
10
+ end
11
+ Proc.new do
12
+ on resource "notifications" do
13
+ run Riddl::Utils::Notifications::Producer::Overview if get
14
+ on resource "topics" do
15
+ run Riddl::Utils::Notifications::Producer::Topics, backend if get
16
+ end
17
+ on resource "subscriptions" do
18
+ run Riddl::Utils::Notifications::Producer::Subscriptions, backend, details if get
19
+ run Riddl::Utils::Notifications::Producer::CreateSubscription, backend, handler if post 'subscribe'
20
+ on resource do
21
+ run Riddl::Utils::Notifications::Producer::Subscription, backend, details if get 'request'
22
+ run Riddl::Utils::Notifications::Producer::UpdateSubscription, backend, handler if put 'details'
23
+ run Riddl::Utils::Notifications::Producer::DeleteSubscription, backend, handler if delete 'delete'
24
+ on resource 'ws' do
25
+ run Riddl::Utils::Notifications::Producer::WS, backend, handler if websocket
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ class HandlerBase #{{{
34
+ def initialize(data)
35
+ @data = data
36
+ @key = nil
37
+ @topics = []
38
+ end
39
+ def key(k)
40
+ @key = k
41
+ self
42
+ end
43
+ def topics(t)
44
+ @topics = t
45
+ self
46
+ end
47
+ def ws_open(socket); end
48
+ def ws_close; end
49
+ def ws_message(socket,data); end
50
+ def create; end
51
+ def delete; end
52
+ def update; end
53
+ end #}}}
54
+
55
+ class Backend #{{{
56
+ attr_reader :topics
57
+
58
+ class Sub #{{{
59
+ def initialize(name)
60
+ @name = name
61
+ end
62
+ def modify(&block)
63
+ XML::Smart.modify(@name,"<subscription xmlns='http://riddl.org/ns/common-patterns/notifications-producer/1.0'/>") do |doc|
64
+ doc.register_namespace 'n', 'http://riddl.org/ns/common-patterns/notifications-producer/1.0'
65
+ block.call doc
66
+ end
67
+ end
68
+ def delete
69
+ FileUtils::rm_rf(File.dirname(@name))
70
+ end
71
+ def to_s
72
+ File.read(@name)
73
+ end
74
+ def read(&block)
75
+ XML::Smart.open_unprotected(@name) do |doc|
76
+ doc.register_namespace 'n', 'http://riddl.org/ns/common-patterns/notifications-producer/1.0'
77
+ block.call doc
78
+ end
79
+ end
80
+ end #}}}
81
+
82
+ class Subs #{{{
83
+ def initialize(target)
84
+ @target = target
85
+ end
86
+
87
+ def each(&block)
88
+ keys.each do |key|
89
+ f = @target + '/' + key + '/subscription.xml'
90
+ block.call Sub.new(f), key if File.exists? f
91
+ end
92
+ end
93
+
94
+ def include?(key)
95
+ f = @target + '/' + key + '/subscription.xml'
96
+ File.exists?(f)
97
+ end
98
+
99
+ def [](key)
100
+ f = @target + '/' + key + '/subscription.xml'
101
+ File.exists?(f) ? Sub.new(f) : nil
102
+ end
103
+
104
+ def create(&block)
105
+ key = nil
106
+ begin
107
+ continue = true
108
+ key = Digest::MD5.hexdigest(Kernel::rand().to_s)
109
+ Dir.mkdir(@target + '/' + key) rescue continue = false
110
+ end until continue
111
+ producer_secret = Digest::MD5.hexdigest(Kernel::rand().to_s)
112
+ consumer_secret = Digest::MD5.hexdigest(Kernel::rand().to_s)
113
+ File.open(@target + '/' + key + '/producer-secret','w') { |f| f.write producer_secret }
114
+ File.open(@target + '/' + key + '/consumer-secret','w') { |f| f.write consumer_secret }
115
+ XML::Smart::modify(@target + '/' + key + '/subscription.xml',"<subscription xmlns='http://riddl.org/ns/common-patterns/notifications-producer/1.0'/>") do |doc|
116
+ doc.register_namespace 'n', 'http://riddl.org/ns/common-patterns/notifications-producer/1.0'
117
+ block.call doc, key
118
+ end
119
+ [key, producer_secret, consumer_secret]
120
+ end
121
+
122
+ def keys
123
+ if File.directory?(@target)
124
+ Dir[@target + '/*'].map do |d|
125
+ File.directory?(d) ? File.basename(d) : nil
126
+ end.compact
127
+ else
128
+ []
129
+ end
130
+ end
131
+ end #}}}
132
+
133
+ def initialize(topics,target)
134
+ @target = target.gsub(/^\/+/,'/')
135
+
136
+ FileUtils::mkdir_p(@target) unless File.exists?(@target)
137
+
138
+ raise "topics file not found" unless File.exists?(topics)
139
+ @topics = XML::Smart.open_unprotected(topics.gsub(/^\/+/,'/'))
140
+ @topics.register_namespace 'n', 'http://riddl.org/ns/common-patterns/notifications-producer/1.0'
141
+
142
+ subscriptions.each do |sub,key|
143
+ sub.read do |doc|
144
+ if doc.find('/*[@url]').empty?
145
+ sub.delete
146
+ end
147
+ end
148
+ end
149
+ end
150
+
151
+ def subscriptions
152
+ Subs.new(@target)
153
+ end
154
+
155
+ end #}}}
156
+
157
+ class Overview < Riddl::Implementation #{{{
158
+ def response
159
+ Riddl::Parameter::Complex.new("overview","text/xml") do
160
+ <<-END
161
+ <overview xmlns='http://riddl.org/ns/common-patterns/notifications-producer/1.0'>
162
+ <topics/>
163
+ <subscriptions/>
164
+ </overview>
165
+ END
166
+ end
167
+
168
+ end
169
+ end #}}}
170
+
171
+ class Topics < Riddl::Implementation #{{{
172
+ def response
173
+ backend = @a[0]
174
+ Riddl::Parameter::Complex.new("overview","text/xml") do
175
+ backend.topics.to_s
176
+ end
177
+ end
178
+ end #}}}
179
+
180
+ class Subscriptions < Riddl::Implementation #{{{
181
+ def response
182
+ backend = @a[0]
183
+ details = @a[1]
184
+ Riddl::Parameter::Complex.new("subscriptions","text/xml") do
185
+ ret = XML::Smart::string <<-END
186
+ <subscriptions details='#{details}' xmlns='http://riddl.org/ns/common-patterns/notifications-producer/1.0'/>
187
+ END
188
+ backend.subscriptions.each do |sub,key|
189
+ sub.read do |doc|
190
+ if doc.root.attributes['url']
191
+ ret.root.add('subscription', :id => key, :url => doc.root.attributes['url'])
192
+ else
193
+ ret.root.add('subscription', :id => key)
194
+ end
195
+ end
196
+ end
197
+ ret.to_s
198
+ end
199
+ end
200
+ end #}}}
201
+
202
+ class Subscription < Riddl::Implementation #{{{
203
+ def response
204
+ backend = @a[0]
205
+ if(backend.subscriptions.include?(@r.last))
206
+ Riddl::Parameter::Complex.new("subscription","text/xml") do
207
+ backend.subscriptions[@r.last].to_s
208
+ end
209
+ else
210
+ @status = 404
211
+ end
212
+ end
213
+ end #}}}
214
+
215
+ class CreateSubscription < Riddl::Implementation #{{{
216
+ def response
217
+ backend = @a[0]
218
+ handler = @a[1]
219
+
220
+ url = @p[0].name == 'url' ? @p.shift.value : nil
221
+
222
+ topics = []
223
+ key, consumer_secret, producer_secret = backend.subscriptions.create do |doc,key|
224
+ doc.root.attributes['url'] = url if url
225
+ while @p.length > 0
226
+ topic = @p.shift.value
227
+ base = @p.shift
228
+ type = base.name
229
+ items = base.value.split(',')
230
+ t = if topics.include?(topic)
231
+ doc.find("/n:subscription/n:topic[@id='#{topic}']").first
232
+ else
233
+ topics << topic
234
+ doc.root.add('topic', :id => topic)
235
+ end
236
+ items.each do |i|
237
+ t.add(type[0..-2], i)
238
+ end
239
+ end
240
+ end
241
+
242
+ handler.key(key).topics(topics).create unless handler.nil?
243
+ [
244
+ Riddl::Parameter::Simple.new('key',key),
245
+ Riddl::Parameter::Simple.new('producer-secret',producer_secret),
246
+ Riddl::Parameter::Simple.new('consumer-secret',consumer_secret)
247
+ ]
248
+ end
249
+ end #}}}
250
+
251
+ class DeleteSubscription < Riddl::Implementation #{{{
252
+ def response
253
+ backend = @a[0]
254
+ handler = @a[1]
255
+ key = @r.last
256
+
257
+ backend.subscriptions[key].delete
258
+ handler.key(key).delete unless handler.nil?
259
+ return
260
+ end
261
+ end #}}}
262
+
263
+ class UpdateSubscription < Riddl::Implementation #{{{
264
+ def response
265
+ backend = @a[0]
266
+ handler = @a[1]
267
+ key = @r.last
268
+
269
+ url = @p[0].name == 'url' ? @p.shift.value : nil
270
+
271
+ # TODO check if message is valid (with producer secret)
272
+ unless backend.subscriptions[key]
273
+ @status = 404
274
+ return # subscription not found
275
+ end
276
+
277
+ topics = []
278
+ backend.subscriptions[key].modify do |doc|
279
+ if url.nil?
280
+ doc.find('/n:subscription/@url').delete_all!
281
+ else
282
+ doc.root.attributes['url'] = url
283
+ end
284
+ doc.root.children.delete_all!
285
+ while @p.length > 1
286
+ topic = @p.shift.value
287
+ base = @p.shift
288
+ type = base.name
289
+ items = base.value.split(',')
290
+ t = if topics.include?(topic)
291
+ doc.find("/n:subscription/n:topic[@id='#{topic}']").first
292
+ else
293
+ topics << topic
294
+ doc.root.add('topic', :id => topic)
295
+ end
296
+ items.each do |i|
297
+ t.add(type[0..-2], i)
298
+ end
299
+ end
300
+ end
301
+
302
+ handler.key(key).topics(topics).update unless handler.nil?
303
+ nil
304
+ end
305
+ end #}}}
306
+
307
+ class WS < Riddl::WebSocketImplementation #{{{
308
+ def onopen
309
+ @backend = @a[0]
310
+ @handler = @a[1]
311
+ @key = @r[-2]
312
+ @handler.key(@key).ws_open(self) unless @handler.nil?
313
+ end
314
+
315
+ def onmessage(data)
316
+ @handler.key(@key).ws_message(data) unless @handler.nil?
317
+ end
318
+
319
+ def onclose
320
+ @handler.key(@key).ws_close() unless @handler.nil?
321
+ end
322
+ end #}}}
323
+
324
+ end
325
+
326
+ end
327
+ end
328
+ end