jaxrsdoc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/bin/jaxrsdoc ADDED
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path("../../lib/parse.rb", __FILE__)
3
+ require File.expand_path("../../lib/site.rb", __FILE__)
4
+ require 'optparse'
5
+ require "rexml/document"
6
+
7
+ options = {}
8
+ optparse = OptionParser.new do |opts|
9
+ opts.banner = "USAGE\n jaxrsdoc [options] source_location"
10
+ opts.separator "\nOPTIONS\n"
11
+
12
+ options[:pattern] = "*Resource.java"
13
+ opts.on( '-p', '--pattern PATTERN', 'Naming pattern of your Jaxrs annotated files java resources. Default is: "*Resource.java".' ) do |pattern|
14
+ options[:pattern] = pattern
15
+ end
16
+
17
+ opts.on( '-m', '--maven', 'Indicates a maven project. Project name & version will be derived the pom.xml at the directory level' ) do |maven|
18
+ options[:maven] = true
19
+ end
20
+
21
+ opts.on( '-a', '--artifact ARTIFACT', 'Name of the artifact/project/module to be included on the website banner.' ) do |artifact_name|
22
+ options[:artifact_name] = artifact_name
23
+ end
24
+
25
+ opts.on( '-v', '--version VERSION', 'Version of your artifact/project/module to be included on the website banner.' ) do |artifact_version|
26
+ options[:artifact_version] = artifact_version
27
+ end
28
+
29
+ opts.on( '-h', '--help', 'Display this screen' ) do
30
+ puts opts
31
+ exit
32
+ end
33
+ end
34
+
35
+ begin
36
+ optparse.parse!
37
+ rescue OptionParser::InvalidOption, OptionParser::InvalidArgument, OptionParser::MissingArgument
38
+ puts "#{$!.message}"
39
+ puts "try 'jaxrsdoc -h' for more information"
40
+ exit
41
+ end
42
+
43
+ resources_location = ARGV.first
44
+
45
+ puts "Looking files recursively at #{resources_location}"
46
+ matched_files = Dir.glob("#{resources_location}/**/#{options[:pattern]}").select{ |entry| File.file?(entry) }
47
+ puts "Found #{matched_files.size} files matching '#{options[:pattern]}'"
48
+
49
+ processed_resources = matched_files.map {|file|
50
+ JaxrsDoc::ResourceParser.parse(File.new(file))
51
+ }.select {|resource| resource.valid? and not resource.nil? }
52
+ puts "Processed #{processed_resources.size} files with a @Path type annotation"
53
+
54
+ project_version = options[:artifact_version]
55
+ project_name = options[:artifact_name]
56
+
57
+ if(options[:maven]) then
58
+ puts "Looking for a pom.xml file at #{resources_location}"
59
+ pom_xml = Dir.glob("#{resources_location}/pom.xml").first
60
+ pom = REXML::Document.new File.new(pom_xml)
61
+ project_name = pom.elements["//artifactId"].first
62
+ project_version = pom.elements["//version"].first
63
+ puts "Found maven project with name: #{project_name}, version: #{project_version}"
64
+ end
65
+
66
+ output_dir = JaxrsDoc::Site.new(processed_resources, Dir.pwd, {:project_version => project_version, :project_name => project_name}).generate
67
+
68
+ puts "Site generated. Open #{output_dir.path}/index.html"
69
+
70
+
@@ -0,0 +1,104 @@
1
+ module JaxrsDoc
2
+
3
+ class Resource
4
+ include Comparable
5
+
6
+ attr_reader :name, :description, :params_descriptions, :path, :verbs, :gets, :posts, :puts, :deletes, :consumes
7
+
8
+ def initialize(file_name, type_annotations, verbs_annotations = {}, type_description = nil, params_descriptions = {})
9
+ @name = file_name
10
+ @description = type_description
11
+ @params_descriptions = params_descriptions
12
+ @path = type_annotations.annotations.find {|a| a.name.eql?"Path"}
13
+ @consumes = type_annotations.annotations.find {|a| a.name.eql?"Consumes"}
14
+ @gets = verbs_annotations[:gets]
15
+ @posts = verbs_annotations[:posts]
16
+ @puts = verbs_annotations[:puts]
17
+ @deletes = verbs_annotations[:deletes]
18
+ @verbs = verbs_annotations
19
+ end
20
+
21
+ def valid?
22
+ not @path.nil?
23
+ end
24
+
25
+ def add_param_description(param_description)
26
+ @params_descriptions.update(param_description)
27
+ end
28
+
29
+ def <=>(another)
30
+ path.value <=> another.path.value
31
+ end
32
+
33
+ def to_s
34
+ "#{@name} [#{@path.value}]"
35
+ end
36
+
37
+ # Support ERB templating of member data.
38
+ def get_binding
39
+ binding
40
+ end
41
+
42
+ end
43
+
44
+ class AnnotationsGroup
45
+
46
+ attr_reader :annotations
47
+
48
+ def initialize(annotations = [])
49
+ @annotations = Array.new(annotations)
50
+ end
51
+
52
+ def method_missing(method_name, *args)
53
+ if(method_name.to_s.include?"params")
54
+ @annotations.select{|a| /\b(Form|FormData|Query)Param\b/ =~ a.name }
55
+ else
56
+ @annotations.find {|a| method_name.to_s.eql?(a.name.downcase) }
57
+ end
58
+ end
59
+
60
+ def empty?
61
+ @annotations.empty?
62
+ end
63
+
64
+ def size
65
+ @annotations.size
66
+ end
67
+
68
+ def to_s
69
+ @annotations.to_s
70
+ end
71
+
72
+ end
73
+
74
+
75
+ class Annotation
76
+
77
+ attr_reader :name, :values, :value
78
+
79
+ def initialize(annotation_text)
80
+ @text = annotation_text.strip
81
+ @name = @text.delete("@").split("(")[0]
82
+ parse_values
83
+ end
84
+
85
+ def to_s
86
+ @text
87
+ end
88
+
89
+ private
90
+
91
+ def parse_values
92
+ @values = []
93
+ if(matches = /\((.*)\)/.match(@text))
94
+ tokens = matches[1].split(",")
95
+ tokens.each { |v|
96
+ @values << v.gsub(/\"|'/, "").strip
97
+ }
98
+ @value = tokens.first.gsub(/\"|'/, "").strip
99
+ end
100
+ end
101
+
102
+ end
103
+
104
+ end
@@ -0,0 +1,3 @@
1
+ module JaxrsDoc
2
+ VERSION = '0.0.1'
3
+ end
data/lib/parse.rb ADDED
@@ -0,0 +1,91 @@
1
+ require File.expand_path("../annotations.rb", __FILE__)
2
+
3
+ module JaxrsDoc
4
+
5
+ module AnnotationScanner
6
+
7
+ JAXRS_ANNOTATIONS = %w[ ApplicationPath Consumes CookieParam DefaultValue
8
+ DELETE Encoded FormParam FormDataParam GET HEAD HeaderParam
9
+ HttpMethod MatrixParam OPTIONS Path PathParam
10
+ POST Produces PUT QueryParam ]
11
+
12
+ def self.scan_annotations(text)
13
+ annotations = []
14
+ text.scan(jaxrs_annotations_regexp) {|s| annotations << JaxrsDoc::Annotation.new(s.first)}
15
+ JaxrsDoc::AnnotationsGroup.new(annotations)
16
+ end
17
+
18
+ private
19
+
20
+ def self.jaxrs_annotations_regexp
21
+ regexp = JAXRS_ANNOTATIONS.map { |a|
22
+ ["#{a}(?=[[:space:]])", "#{a}\\(?.*?\\)"]
23
+ }
24
+ Regexp.new("@(#{regexp.join('|')})")
25
+ end
26
+
27
+ end
28
+
29
+ module ParamDescriptionScanner
30
+
31
+ def self.scan_params_descriptions(text)
32
+ params_descriptions = Hash.new("")
33
+ text.each_line { |line|
34
+ if(param_index = line.index("@param"))
35
+ param_name, param_desc = line[(param_index + 6)..-1].split(" ", 2);
36
+ params_descriptions.store(param_name, param_desc)
37
+ end
38
+ }
39
+ params_descriptions
40
+ end
41
+
42
+ end
43
+
44
+ module ResourceParser
45
+ include AnnotationScanner
46
+
47
+ def self.parse(file)
48
+ @filename = File.basename(file.path)
49
+ parse_content(file.read)
50
+ end
51
+
52
+ def self.parse_content(text)
53
+ verbs_annotations = {:gets => [], :posts => [], :puts => [], :deletes => []}
54
+ descriptions = {}
55
+ java_sections = text.split(/(?<=\s)({)/);
56
+ resource_head_section = java_sections.shift
57
+ type_annotations = AnnotationScanner.scan_annotations(resource_head_section)
58
+ descriptions.update(ParamDescriptionScanner.scan_params_descriptions(resource_head_section))
59
+ type_description = parse_resource_description(resource_head_section)
60
+ java_sections.each { |section|
61
+ group = AnnotationScanner.scan_annotations(section)
62
+ descriptions.update(ParamDescriptionScanner.scan_params_descriptions(section))
63
+ unless group.empty?
64
+ verbs_annotations[:gets] << group if(group.get)
65
+ verbs_annotations[:posts] << group if(group.post)
66
+ verbs_annotations[:puts] << group if(group.put)
67
+ verbs_annotations[:deletes] << group if(group.delete)
68
+ end
69
+ }
70
+ JaxrsDoc::Resource.new(@filename, type_annotations, verbs_annotations, type_description, descriptions)
71
+ end
72
+
73
+ private
74
+
75
+ def self.parse_resource_description(head_text_section)
76
+ from_package_only_head_section = head_text_section.each_line.drop_while {|line|
77
+ not line.strip.start_with?("package")
78
+ }.join
79
+
80
+ if (description_match = /^\/\*\*(.+)\*\/$/m.match(from_package_only_head_section))
81
+ full_text = description_match[1].gsub("*", "")
82
+ description = ""
83
+ full_text.each_line { |line|
84
+ description << line unless line.include?("@param")
85
+ }
86
+ description
87
+ end
88
+ end
89
+
90
+ end
91
+ end
data/lib/site.rb ADDED
@@ -0,0 +1,60 @@
1
+ require File.expand_path("../templates.rb", __FILE__)
2
+ require 'erb'
3
+ require 'fileutils'
4
+
5
+ module JaxrsDoc
6
+
7
+ class Site
8
+
9
+ attr_reader :resources, :project_version, :project_name, :output_dir
10
+
11
+ def initialize(resources, output_location, options = {})
12
+ @resources = resources.sort!
13
+ @project_version = options[:project_version]
14
+ @project_name = options[:project_name]
15
+ make_output_dir(output_location)
16
+ copy_resources_to_output_dir
17
+ end
18
+
19
+ def generate
20
+ @resources.each { |resource|
21
+ File.open(resource_file_path(resource.name), "w") { |f|
22
+ content = ERB.new(JaxrsDoc::Templates.get_resource_page).result(binding)
23
+ f.syswrite(content)
24
+ }
25
+ }
26
+
27
+ File.open(index_file_path, "w") { |f|
28
+ content = ERB.new(JaxrsDoc::Templates.get_index_page).result(binding)
29
+ f.syswrite(content)
30
+ }
31
+ @output_dir
32
+ end
33
+
34
+ private
35
+
36
+ def resource_file_path(resource_name)
37
+ File.join(@output_dir.path, "#{resource_name}.html")
38
+ end
39
+
40
+ def index_file_path
41
+ File.join(@output_dir.path, "index.html")
42
+ end
43
+
44
+ def make_output_dir(output_location)
45
+ output_path = "#{output_location}"
46
+ output_path << "/jaxrsdoc"
47
+ output_path << "/#{@project_name}" unless @project_name.nil?
48
+ output_path << "/#{@project_version}" unless @project_version.nil?
49
+ FileUtils.mkdir_p(output_path)
50
+ @output_dir = Dir.new(output_path)
51
+ end
52
+
53
+ def copy_resources_to_output_dir
54
+ bootstrap_file_path = File.expand_path("../../site/bootstrap.css", __FILE__)
55
+ jaxrsdoc_css_file_path = File.expand_path("../../site/jaxrsdoc.css", __FILE__)
56
+ FileUtils.cp(bootstrap_file_path, File.join(@output_dir.path, "bootstrap.css"))
57
+ FileUtils.cp(jaxrsdoc_css_file_path, File.join(@output_dir.path, "jaxrsdoc.css"))
58
+ end
59
+ end
60
+ end
data/lib/templates.rb ADDED
@@ -0,0 +1,208 @@
1
+ module JaxrsDoc
2
+
3
+ module Templates
4
+
5
+ def self.get_index_page
6
+ %q{
7
+ <html>
8
+ <head>
9
+ <link rel="stylesheet" type="text/css" href="bootstrap.css" />
10
+ <link rel="stylesheet" type="text/css" href="jaxrsdoc.css" />
11
+ </head>
12
+ <body>
13
+ <div class="navbar">
14
+ <div class="navbar-inner">
15
+ <div class="container">
16
+ <a class="brand" href="#"><%= @project_name %> <%= @project_version %></a>
17
+ <ul class="nav">
18
+ <li class="active"><a href="index.html">API index</a></li>
19
+ </ul>
20
+ <p class="navbar-text pull-right">Last update <%= Time.now.strftime("%d %B - %H:%M:%S") %></p>
21
+ </div>
22
+ </div>
23
+ </div>
24
+ <div class="container">
25
+ <% @resources.each_slice(20) do |big_packets_of_resources| %>
26
+ <div class="row">
27
+ <% big_packets_of_resources.each_slice(10) do |small_packets_of_resources|%>
28
+ <div class="span6">
29
+ <pre><ul><% small_packets_of_resources.each do |resource|%><li><a href="<%= resource.name %>.html"> <% if resource.path %><%= resource.path.value %><% end %></a></li><% end%></ul></pre>
30
+ </div>
31
+ <% end %>
32
+ </div>
33
+ <% end%>
34
+ <footer class="modal-footer"><span>Powered by <a href="https://github.com/simcap/jaxrsdoc">Jaxrsdoc</a></span></footer>
35
+ </div>
36
+ <body>
37
+ </html>
38
+ }
39
+ end
40
+
41
+ def self.get_resource_page
42
+ %q{
43
+ <html>
44
+ <head>
45
+ <link rel="stylesheet" type="text/css" href="bootstrap.css" />
46
+ <link rel="stylesheet" type="text/css" href="jaxrsdoc.css" />
47
+ </head>
48
+ <body>
49
+ <div class="navbar">
50
+ <div class="navbar-inner">
51
+ <div class="container">
52
+ <a class="brand" href="#"><%= @project_name %> <%= @project_version %></a>
53
+ <ul class="nav">
54
+ <li class="active"><a href="index.html">API index</a></li>
55
+ </ul>
56
+ <p class="navbar-text pull-right">Updated <%= Time.now.strftime("%d %B - %H:%M:%S") %></p>
57
+ </div>
58
+ </div>
59
+ </div>
60
+
61
+ <div class="container">
62
+
63
+ <div class="page-header">
64
+ <h1><% if resource.path %><%= resource.path.value %><% end %><pre class="pull-right"><%= resource.name %></pre></h1>
65
+ </div>
66
+
67
+ <% if resource.description %>
68
+ <div>
69
+ <pre><%= resource.description %></pre>
70
+ </div>
71
+ <% end %>
72
+
73
+ <% resource.gets.each do |annot_group| %>
74
+ <div class="row">
75
+ <div class="get span12">
76
+ <button class="btn btn-success pull-left disabled" href="#"><%= annot_group.get.name %></button>
77
+ <h3 class="pagination-centered"><% if annot_group.path %> <%= annot_group.path.value %> <% end %></h3>
78
+ </div>
79
+ </div>
80
+
81
+ <% unless annot_group.queryparams.empty? %>
82
+ <div class="row">
83
+ <div class="span12">
84
+ <table class="table table-bordered table-striped">
85
+ <colgroup>
86
+ <col class="span1">
87
+ </colgroup>
88
+ <thead>
89
+ <tr><th>Parameter</th><th>Description</th></tr>
90
+ </thead>
91
+ <tbody>
92
+ <% annot_group.queryparams.each do |param| %>
93
+ <tr>
94
+ <td><%= param.value %></td>
95
+ <td><%= resource.params_descriptions[param.value] %></td>
96
+ </tr>
97
+ <% end %>
98
+ </tbody>
99
+ </table>
100
+ </div>
101
+ </div>
102
+ <% end %>
103
+ <% end %>
104
+
105
+ <% resource.posts.each do |annot_group| %>
106
+ <div class="row">
107
+ <div class="post span12">
108
+ <button class="btn btn-info pull-left disabled" href="#"><%= annot_group.post.name %></button>
109
+ <h3 class="pagination-centered"><% if annot_group.path %> <%= annot_group.path.value %> <% end %></h3>
110
+ </div>
111
+ </div>
112
+
113
+ <% unless annot_group.params.empty? %>
114
+ <div class="row">
115
+ <div class="span12">
116
+ <table class="table table-bordered table-striped">
117
+ <colgroup>
118
+ <col class="span1">
119
+ </colgroup>
120
+ <thead>
121
+ <tr><th>Parameter</th><th>Description</th></tr>
122
+ </thead>
123
+ <tbody>
124
+ <% annot_group.params.each do |param| %>
125
+ <tr>
126
+ <td><%= param.value %></td>
127
+ <td><%= resource.params_descriptions[param.value] %></td>
128
+ </tr>
129
+ <% end %>
130
+ </tbody>
131
+ </table>
132
+ </div>
133
+ </div>
134
+ <% end %>
135
+ <% end %>
136
+
137
+ <% resource.puts.each do |annot_group| %>
138
+ <div class="row">
139
+ <div class="put span12">
140
+ <button class="btn btn-warning pull-left disabled" href="#"><%= annot_group.put.name %></button>
141
+ <h3 class="pagination-centered"><% if annot_group.path %> <%= annot_group.path.value %> <% end %></h3>
142
+ </div>
143
+ </div>
144
+
145
+ <% unless annot_group.params.empty? %>
146
+ <div class="row">
147
+ <div class="span12">
148
+ <table class="table table-bordered table-striped">
149
+ <colgroup>
150
+ <col class="span1">
151
+ </colgroup>
152
+ <thead>
153
+ <tr><th>Parameter</th><th>Description</th></tr>
154
+ </thead>
155
+ <tbody>
156
+ <% annot_group.params.each do |param| %>
157
+ <tr>
158
+ <td><%= param.value %></td>
159
+ <td><%= resource.params_descriptions[param.value] %></td>
160
+ </tr>
161
+ <% end %>
162
+ </tbody>
163
+ </table>
164
+ </div>
165
+ </div>
166
+ <% end %>
167
+ <% end %>
168
+
169
+ <% resource.deletes.each do |annot_group| %>
170
+ <div class="row">
171
+ <div class="post span12">
172
+ <button class="btn btn-danger pull-left disabled" href="#"><%= annot_group.delete.name %></button>
173
+ <h3 class="pagination-centered"><% if annot_group.path %> <%= annot_group.path.value %> <% end %></h3>
174
+ </div>
175
+ </div>
176
+
177
+ <% unless annot_group.params.empty? %>
178
+ <div class="row">
179
+ <div class="span12">
180
+ <table class="table table-bordered table-striped">
181
+ <colgroup>
182
+ <col class="span1">
183
+ </colgroup>
184
+ <thead>
185
+ <tr><th>Parameter</th><th>Description</th></tr>
186
+ </thead>
187
+ <tbody>
188
+ <% annot_group.params.each do |param| %>
189
+ <tr>
190
+ <td><%= param.value %></td>
191
+ <td><%= resource.params_descriptions[param.value] %></td>
192
+ </tr>
193
+ <% end %>
194
+ </tbody>
195
+ </table>
196
+ </div>
197
+ </div>
198
+ <% end %>
199
+ <% end %>
200
+
201
+
202
+ </div>
203
+ <body>
204
+ </html>
205
+ }
206
+ end
207
+ end
208
+ end