1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
21 # Specific handler for nitweb API.
22 abstract class APIHandler
25 # The JSON API does not filter anything by default.
27 # So we can cache the model view.
28 var view
: ModelView is lazy
do
29 var view
= new ModelView(model
)
30 view
.min_visibility
= private_visibility
31 view
.include_fictive
= true
32 view
.include_empty_doc
= true
33 view
.include_attribute
= true
34 view
.include_test_suite
= true
38 # Try to load the mentity from uri with `/:id`.
40 # Send 400 if `:id` is null.
41 # Send 404 if no entity is found.
42 # Return null in both cases.
43 fun mentity_from_uri
(req
: HttpRequest, res
: HttpResponse): nullable MEntity do
44 var id
= req
.param
("id")
49 var mentity
= find_mentity
(view
, id
)
50 if mentity
== null then
57 # Group all api handlers in one router.
61 # Model to pass to handlers.
64 # ModelBuilder to pass to handlers.
65 var modelbuilder
: ModelBuilder
67 # Mainmodule to pass to handlers.
68 var mainmodule
: MModule
71 use
("/list", new APIList(model
, mainmodule
))
72 use
("/search", new APISearch(model
, mainmodule
))
73 use
("/random", new APIRandom(model
, mainmodule
))
74 use
("/entity/:id", new APIEntity(model
, mainmodule
))
75 use
("/code/:id", new APIEntityCode(model
, mainmodule
, modelbuilder
))
76 use
("/uml/:id", new APIEntityUML(model
, mainmodule
))
80 # Search mentities from a query string.
82 # Example: `GET /search?q=Arr`
86 redef fun get
(req
, res
) do
87 var q
= req
.string_arg
("q")
92 var arr
= new JsonArray
93 for mentity
in view
.mentities
do
94 if mentity
.name
.has_prefix
(q
) then arr
.add mentity
100 # List all mentities.
102 # MEntities can be filtered on their kind using the `k` parameter.
103 # Allowed kinds are `package`, `group`, `module`, `class`, `classdef`, `property`, `propdef`.
105 # List size can be limited with the `n` parameter.
107 # Example: `GET /list?k=module?n=10`
111 # List mentities depending on the `k` kind parameter.
112 fun list_mentities
(req
: HttpRequest): Array[MEntity] do
113 var k
= req
.string_arg
("k")
114 var mentities
= new Array[MEntity]
115 if k
== "package" then
116 for mentity
in view
.mpackages
do mentities
.add mentity
117 else if k
== "group" then
118 for mentity
in view
.mgroups
do mentities
.add mentity
119 else if k
== "module" then
120 for mentity
in view
.mmodules
do mentities
.add mentity
121 else if k
== "class" then
122 for mentity
in view
.mclasses
do mentities
.add mentity
123 else if k
== "classdef" then
124 for mentity
in view
.mclassdefs
do mentities
.add mentity
125 else if k
== "property" then
126 for mentity
in view
.mproperties
do mentities
.add mentity
127 else if k
== "propdef" then
128 for mentity
in view
.mpropdefs
do mentities
.add mentity
130 for mentity
in view
.mentities
do mentities
.add mentity
135 # Limit mentities depending on the `n` parameter.
136 fun limit_mentities
(req
: HttpRequest, mentities
: Array[MEntity]): Array[MEntity] do
137 var n
= req
.int_arg
("n")
139 return mentities
.sub
(0, n
)
144 redef fun get
(req
, res
) do
145 var mentities
= list_mentities
(req
)
146 mentities
= limit_mentities
(req
, mentities
)
147 var arr
= new JsonArray
148 for mentity
in mentities
do arr
.add mentity
153 # Return a random list of MEntities.
155 # Example: `GET /random?n=10&k=module`
159 # Randomize mentities order.
160 fun randomize_mentities
(req
: HttpRequest, mentities
: Array[MEntity]): Array[MEntity] do
161 var res
= mentities
.to_a
166 redef fun get
(req
, res
) do
167 var mentities
= list_mentities
(req
)
168 mentities
= limit_mentities
(req
, mentities
)
169 mentities
= randomize_mentities
(req
, mentities
)
170 var arr
= new JsonArray
171 for mentity
in mentities
do arr
.add mentity
176 # Return the JSON representation of a MEntity.
178 # Example: `GET /entity/core::Array`
182 redef fun get
(req
, res
) do
183 var mentity
= mentity_from_uri
(req
, res
)
184 if mentity
== null then return
185 res
.json mentity
.api_json
(self)
190 # Return a UML representation of MEntity.
192 # Example: `GET /entity/core::Array/uml`
196 redef fun get
(req
, res
) do
197 var mentity
= mentity_from_uri
(req
, res
)
199 if mentity
isa MClassDef then mentity
= mentity
.mclass
200 if mentity
isa MClass then
201 var uml
= new UMLModel(view
, mainmodule
)
202 dot
= uml
.generate_class_uml
.write_to_string
203 else if mentity
isa MModule then
204 var uml
= new UMLModel(view
, mentity
)
205 dot
= uml
.generate_package_uml
.write_to_string
210 res
.send render_svg
(dot
)
213 # Render a `dot` string as a svg image.
214 fun render_svg
(dot
: String): String do
215 var proc
= new ProcessDuplex("dot", "-Tsvg")
216 var svg
= proc
.write_and_read
(dot
)
223 # Return the source code of MEntity.
225 # Example: `GET /entity/core::Array/code`
229 # Modelbuilder used to access sources.
230 var modelbuilder
: ModelBuilder
232 redef fun get
(req
, res
) do
233 var mentity
= mentity_from_uri
(req
, res
)
234 if mentity
== null then return
235 var source
= render_source
(mentity
)
236 if source
== null then
243 # Highlight `mentity` source code.
244 private fun render_source
(mentity
: MEntity): nullable HTMLTag do
245 var node
= modelbuilder
.mentity2node
(mentity
)
246 if node
== null then return null
247 var hl
= new HighlightVisitor