restility 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require "rest"
4
+
5
+ class DocBookPrinter < Printer
6
+
7
+ attr_accessor :output_dir
8
+
9
+ def initialize
10
+ super()
11
+ @output_dir = "docbook"
12
+ @xml_examples = Hash.new
13
+ @xml_schemas = Hash.new
14
+ @section = 0
15
+
16
+ @html_tag_mapping = {
17
+ "tt" => nil,
18
+ "em" => "emphasis",
19
+ "b" => "emphasis",
20
+ }
21
+ end
22
+
23
+ def do_prepare
24
+ unless File.exists? @output_dir
25
+ Dir.mkdir @output_dir
26
+ end
27
+
28
+ @index = File.new @output_dir + "/rest_api_appendix.xml", "w"
29
+ @xml = Builder::XmlMarkup.new :target => @index, :indent => 2
30
+ @xml.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
31
+ @xml.declare! :DOCTYPE, :appendix, :PUBLIC, "-//Novell//DTD NovDoc XML V1.0//EN", "novdocx.dtd" do |x|
32
+ x.declare! :ENTITY, :%, :'NOVDOC.DEACTIVATE.IDREF', "IGNORE"
33
+ x.declare! :ENTITY, :%, :entities, :SYSTEM, "entity-decl.ent"
34
+ x << " %entities;\n"
35
+ end
36
+
37
+ @xml.comment! "This file was generated by restility at #{Time.now}"
38
+
39
+ @xml << "<appendix xml:base=\"rest_api_appendix.xml\" id=\"app.rest_api_doc\">\n"
40
+ end
41
+
42
+ def do_finish
43
+ @xml << "</appendix>\n"
44
+ puts "Written #{@index.path}"
45
+ @index.close
46
+ end
47
+
48
+ def print_section section
49
+ if !section.root?
50
+ level = section.level - 1
51
+
52
+ if level.zero?
53
+ @xml.title section
54
+ @xml.para
55
+ section.print_children self
56
+ else
57
+ @xml.tag! "sect#{level}", "id" => "app.rest_api_doc.sect#{level}.#{@section}" do
58
+ @section += 1
59
+ @xml.title section
60
+ section.print_children self
61
+ end
62
+ end
63
+ else
64
+ section.print_children self
65
+ end
66
+ end
67
+
68
+ def print_request request
69
+ @xml.variablelist do
70
+ @xml.varlistentry do
71
+
72
+ @xml.term do
73
+ @xml.literal request.to_s
74
+ end
75
+
76
+ @xml.listitem do
77
+ request.parameters.each do |p|
78
+ @xml.para do
79
+ @xml.emphasis p.name
80
+ @xml << " (optional)" if p.optional
81
+ @xml << " - #{p.description}" if p.description && !p.description.empty?
82
+ end
83
+ end
84
+
85
+ request.print_children self
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ def replace_html_tags text
92
+ @html_tag_mapping.each do |html, docbook|
93
+ if docbook.nil?
94
+ text.gsub! "<#{html}>", ""
95
+ else
96
+ text.gsub! "<#{html}>", "<#{docbook}>"
97
+ text.gsub! "</#{html}>", "</#{docbook}>"
98
+ end
99
+ end
100
+ end
101
+
102
+ def print_text text
103
+ @xml.para do |p|
104
+ text.text.each do |t|
105
+ replace_html_tags t
106
+ p << t << "\n"
107
+ end
108
+ end
109
+ end
110
+
111
+ def print_parameter parameter
112
+ end
113
+
114
+ def print_host host
115
+ @xml.para "Host: " + host.name
116
+ end
117
+
118
+ def print_result result
119
+ @xml.para "Result: #{result.name}"
120
+ end
121
+
122
+ def print_body body
123
+ @xml.para "Body: #{body.name}"
124
+ end
125
+
126
+ def print_xmlresult result
127
+ print_xml_links result.name, result.schema
128
+ end
129
+
130
+ def print_xmlbody body
131
+ print_xml_links body.name, body.schema
132
+ end
133
+
134
+ def print_xml_links xmlname, schema
135
+ example = xmlname + ".xml"
136
+ if !schema || schema.empty?
137
+ schema = xmlname + ".xsd"
138
+ end
139
+
140
+ if XmlFile.exist? example
141
+ @xml.screen File.read(XmlFile.find_file example)
142
+ end
143
+
144
+ if XmlFile.exist? schema
145
+ @xml.screen File.read(XmlFile.find_file schema)
146
+ end
147
+ end
148
+
149
+ def print_contents contents
150
+ # empty, the content is generated by docbook itself
151
+ @xml.para
152
+ end
153
+
154
+ def print_version version
155
+ @xml.para "API Version: #{version}"
156
+ end
157
+
158
+ end
data/lib/rest.rb ADDED
@@ -0,0 +1,459 @@
1
+ #!/usr/bin/ruby
2
+
3
+ class XmlFile
4
+
5
+ @@include_dir = ""
6
+
7
+ def XmlFile.include_dir= dir
8
+ if !dir
9
+ dir = ""
10
+ end
11
+ @@include_dir = dir
12
+ end
13
+
14
+ def XmlFile.exist? file_name
15
+ exists? file_name
16
+ end
17
+
18
+ def XmlFile.exists? file_name
19
+ find_file file_name
20
+ end
21
+
22
+ def XmlFile.copy file_name, output_dir
23
+ dir_name = File.dirname( file_name )
24
+
25
+ if ( dir_name =~ /^\// )
26
+ puts STDERR, "Absolute file names aren't allowed as XML file names."
27
+ + " (#{dir_name})";
28
+ return
29
+ end
30
+
31
+ if ( dir_name )
32
+ output_dir += "/" + dir_name
33
+ end
34
+
35
+ if ( dir_name && !dir_name.empty? && !File.exist?( dir_name ) )
36
+ `mkdir -p #{output_dir}`
37
+ if ( $? != 0 )
38
+ puts STDERR, "Unable to create directory '#{dir_name}'"
39
+ end
40
+ end
41
+ src_file = find_file( file_name )
42
+ unless File.absolute_path(output_dir) == File.absolute_path(File.split( src_file).first)
43
+ # do not copy to itself
44
+ FileUtils.cp( src_file, output_dir )
45
+ end
46
+
47
+ end
48
+
49
+ def XmlFile.find_file file_name
50
+ if ( File.exists? file_name )
51
+ return file_name
52
+ end
53
+
54
+ if ( !@@include_dir.empty? )
55
+ file_name = @@include_dir + "/" + file_name
56
+ if ( File.exists? file_name )
57
+ return file_name
58
+ end
59
+ end
60
+
61
+ return nil
62
+ end
63
+
64
+ end
65
+
66
+ class Node
67
+ attr_accessor :parent, :level, :name
68
+ attr_reader :children
69
+
70
+ def initialize n = nil
71
+ @name = n
72
+ @children = Array.new
73
+ @level = 0
74
+ end
75
+
76
+ def add_child c
77
+ @children.push c
78
+ c.parent = self
79
+ c.level = @level + 1
80
+ end
81
+
82
+ def print printer
83
+ printer.do_print self
84
+ end
85
+
86
+ def print_children printer
87
+ if ( @children )
88
+ @children.each do |child|
89
+ child.print printer
90
+ end
91
+ end
92
+ end
93
+
94
+ def root?
95
+ return !parent
96
+ end
97
+
98
+ def root
99
+ if parent
100
+ return parent.root
101
+ end
102
+ return self
103
+ end
104
+
105
+ def to_s
106
+ @name
107
+ end
108
+
109
+ def all_children type
110
+ @result = Array.new
111
+ @children.each do |child|
112
+ if ( child.class == type )
113
+ @result.push child
114
+ end
115
+ @result.concat( child.all_children( type ) )
116
+ end
117
+ @result
118
+ end
119
+
120
+ end
121
+
122
+ class Section < Node
123
+ end
124
+
125
+ class Request < Node
126
+
127
+ attr_accessor :verb, :path, :id
128
+
129
+ @@id = 0
130
+
131
+ def initialize
132
+ @id = @@id;
133
+ @@id += 1
134
+ super()
135
+ end
136
+
137
+ def to_s
138
+ p = @path.gsub(/<([^>]*?)\??>=/, "\\1=")
139
+ @verb + " " + p
140
+ end
141
+
142
+ def parameters
143
+ result = Array.new
144
+ @path.scan( /[^=]<(.*?)(\??)>/ ) do |p|
145
+ node = self
146
+ found = false
147
+ optional = $2.empty? ? false : true
148
+ while( node && !found )
149
+ node.children.each do |c|
150
+ if ( c.is_a?( Parameter ) && c.name == $1 )
151
+ c.optional = optional
152
+ result.push c
153
+ found = true
154
+ break
155
+ end
156
+ end
157
+ node = node.parent
158
+ end
159
+ if ( !found )
160
+ n = Parameter.new( $1 )
161
+ n.optional = optional
162
+ result.push n
163
+ end
164
+ end
165
+ result
166
+ end
167
+
168
+ def host
169
+ node = self
170
+ while( node )
171
+ node.children.each do |c|
172
+ if c.is_a? Host
173
+ return c
174
+ end
175
+ end
176
+ node = node.parent
177
+ end
178
+ nil
179
+ end
180
+
181
+ end
182
+
183
+ class Text < Node
184
+
185
+ attr_accessor :text
186
+
187
+ def initialize
188
+ @text = Array.new
189
+ super()
190
+ end
191
+
192
+ def to_s
193
+ @text.join("\n")
194
+ end
195
+
196
+ def append t
197
+ @text.push t
198
+ end
199
+
200
+ end
201
+
202
+ class Parameter < Node
203
+
204
+ attr_accessor :description, :optional
205
+
206
+ def initialize n = nil
207
+ @optional = false
208
+ super
209
+ end
210
+
211
+ def to_s
212
+ s = @name.to_s
213
+ s += " (optional)" if @optional
214
+ if ( !@description || @description.empty? )
215
+ s
216
+ else
217
+ s + " - " + @description
218
+ end
219
+ end
220
+
221
+ end
222
+
223
+ class Xml < Node
224
+ attr_accessor :schema
225
+ end
226
+
227
+ class Body < Node
228
+ end
229
+
230
+ class Result < Node
231
+ end
232
+
233
+ class XmlBody < Xml
234
+ end
235
+
236
+ class XmlResult < Xml
237
+ end
238
+
239
+ class Host < Node
240
+ end
241
+
242
+ class Contents < Node
243
+ end
244
+
245
+ class Version < Node
246
+ end
247
+
248
+ class Document < Section
249
+
250
+ def initialize
251
+ super
252
+ self.name = "DOCUMENT"
253
+ end
254
+
255
+ def parse_args
256
+ sections = Hash.new
257
+
258
+ sections[ 0 ] = self
259
+
260
+ @section = nil
261
+
262
+ while line = gets
263
+ if ( line =~ /^\s+(\S.*)$/ )
264
+ if ( !@text )
265
+ @text = Text.new
266
+ end
267
+ @text.append $1
268
+ else
269
+ if ( @text && @current )
270
+ @current.add_child @text
271
+ end
272
+ @text = nil
273
+ end
274
+
275
+ if ( line =~ /^(=+) (.*)/ )
276
+ level = $1.size
277
+ title = $2
278
+
279
+ @section = Section.new title
280
+ @current = @section
281
+
282
+ parent = sections[ level - 1 ]
283
+ parent.add_child @section
284
+ sections[ level ] = @section
285
+
286
+ elsif ( line =~ /^(GET|PUT|POST|DELETE) (.*)/ )
287
+ @request = Request.new
288
+ @current = @request
289
+
290
+ @request.verb = $1
291
+ @request.path = $2
292
+
293
+ @section.add_child( @request )
294
+
295
+ elsif ( line =~ /^<(.*)>: (.*)/ )
296
+ parameter = Parameter.new
297
+
298
+ parameter.name = $1
299
+ parameter.description = $2
300
+
301
+ @current.add_child( parameter )
302
+
303
+ elsif ( line =~ /^Host: (.*)/ )
304
+ host = Host.new $1
305
+ @current.add_child( host )
306
+
307
+ elsif ( line =~ /^Body: (.*)/ )
308
+ body = Body.new $1
309
+ @current.add_child( body )
310
+
311
+ elsif ( line =~ /^Result: (.*)/ )
312
+ result = Result.new $1
313
+ @current.add_child( result )
314
+
315
+ elsif ( line =~ /^XmlBody: (.*)/ )
316
+ body = XmlBody.new $1
317
+ @current.add_child( body )
318
+
319
+ elsif ( line =~ /^XmlResult: (.*) +(.*)/ )
320
+ result = XmlResult.new $1
321
+ result.schema = $2
322
+ @current.add_child( result )
323
+
324
+ elsif ( line =~ /^XmlResult: (.*)/ )
325
+ result = XmlResult.new $1
326
+ @current.add_child( result )
327
+
328
+ elsif ( line =~ /^Contents/ )
329
+ @current.add_child( Contents.new )
330
+
331
+ elsif ( line =~ /^Version: (.*)/ )
332
+ version = Version.new $1
333
+ @current.add_child( version )
334
+
335
+ end
336
+
337
+ end
338
+ end
339
+
340
+ end
341
+
342
+
343
+ class Printer
344
+
345
+ def initialize
346
+ @missing = Hash.new
347
+ end
348
+
349
+ def print node
350
+ do_prepare
351
+ do_print node
352
+ do_finish
353
+ end
354
+
355
+ def print_document printer
356
+ print_section printer
357
+ end
358
+
359
+ def do_print node
360
+ method = "print_" + node.class.to_s.downcase
361
+ send method, node
362
+ end
363
+
364
+ def do_prepare
365
+ end
366
+
367
+ def do_finish
368
+ end
369
+
370
+ def method_missing symbol, *args
371
+ if ( !@missing[ symbol ] )
372
+ @missing[ symbol ] = true
373
+ STDERR.puts "Warning: #{self.class} doesn't support '#{symbol}'."
374
+ end
375
+ end
376
+
377
+ end
378
+
379
+ class TextPrinter < Printer
380
+
381
+ def indent node
382
+ node.level.times do
383
+ printf " "
384
+ end
385
+ end
386
+
387
+ def print_section section
388
+ indent section
389
+ puts "SECTION " + section.to_s
390
+ section.print_children self
391
+ end
392
+
393
+ def print_request request
394
+ indent request
395
+ puts "Request: " + request.to_s
396
+ host = request.host
397
+ if ( host )
398
+ indent host
399
+ puts " HOST: " + host.name
400
+ end
401
+ request.parameters.each do |p|
402
+ indent request
403
+ puts " PARAMETER: #{p.to_s}"
404
+ end
405
+ request.print_children self
406
+ end
407
+
408
+ def print_text text
409
+ text.text.each do |t|
410
+ indent text
411
+ puts t
412
+ end
413
+ end
414
+
415
+ def print_parameter parameter
416
+ indent parameter
417
+ puts "PARAMETER_DEF: " + parameter.name + " - " + parameter.description
418
+ end
419
+
420
+ def print_host host
421
+ indent host
422
+ puts "HOST_DEF: " + host.name
423
+ end
424
+
425
+ def print_result result
426
+ indent result
427
+ puts "Result: " + result.name
428
+ end
429
+
430
+ def print_xmlresult result
431
+ indent result
432
+ printf "XmlResult: " + result.name
433
+ if ( result.schema )
434
+ printf " (Schema: #{result.schema})"
435
+ end
436
+ printf "\n"
437
+ end
438
+
439
+ def print_body body
440
+ indent body
441
+ puts "Body: " + body.name
442
+ end
443
+
444
+ end
445
+
446
+
447
+ class OutlinePrinter < Printer
448
+ def print node
449
+ node.level.times do
450
+ printf " "
451
+ end
452
+ puts "#{node.level} #{node.class}"
453
+ node.print_children self
454
+ end
455
+
456
+ def print_section node
457
+ print node
458
+ end
459
+ end