b7c35c0d538c9f517715094f396b256df646e502
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.
20 import model
::model_index
25 use
("/list", new APIList(config
))
26 use
("/search", new APISearch(config
))
27 use
("/random", new APIRandom(config
))
28 use
("/entity/:id", new APIEntity(config
))
29 use
("/entity/:id/doc", new APIEntityDoc(config
))
30 use
("/code/:id", new APIEntityCode(config
))
31 use
("/uml/:id", new APIEntityUML(config
))
32 use
("/linearization/:id", new APIEntityLinearization(config
))
33 use
("/defs/:id", new APIEntityDefs(config
))
34 use
("/inheritance/:id", new APIEntityInheritance(config
))
40 # MEntities can be filtered on their kind using the `k` parameter.
41 # Allowed kinds are `package`, `group`, `module`, `class`, `classdef`, `property`, `propdef`.
43 # List size can be limited with the `n` parameter.
45 # Example: `GET /list?k=module?n=10`
49 # List mentities depending on the `k` kind parameter.
50 fun list_mentities
(req
: HttpRequest): Array[MEntity] do
51 var k
= req
.string_arg
("k")
52 var mentities
= new Array[MEntity]
53 if k
== "package" then
54 for mentity
in config
.view
.mpackages
do mentities
.add mentity
55 else if k
== "group" then
56 for mentity
in config
.view
.mgroups
do mentities
.add mentity
57 else if k
== "module" then
58 for mentity
in config
.view
.mmodules
do mentities
.add mentity
59 else if k
== "class" then
60 for mentity
in config
.view
.mclasses
do mentities
.add mentity
61 else if k
== "classdef" then
62 for mentity
in config
.view
.mclassdefs
do mentities
.add mentity
63 else if k
== "property" then
64 for mentity
in config
.view
.mproperties
do mentities
.add mentity
65 else if k
== "propdef" then
66 for mentity
in config
.view
.mpropdefs
do mentities
.add mentity
68 for mentity
in config
.view
.mentities
do mentities
.add mentity
73 # Filter mentities based on the config view filters
74 fun filter_mentities
(req
: HttpRequest, mentities
: Array[MEntity]): Array[MEntity] do
75 var res
= new Array[MEntity]
76 for mentity
in mentities
do
77 if config
.view
.filter
.accept_mentity
(mentity
) then res
.add mentity
82 # Sort mentities by lexicographic order
84 # TODO choose order from request
85 fun sort_mentities
(req
: HttpRequest, mentities
: Array[MEntity]): Array[MEntity] do
86 var sorted
= mentities
.to_a
87 var sorter
= new MEntityNameSorter
92 # Limit mentities depending on the `n` parameter.
93 fun limit_mentities
(req
: HttpRequest, mentities
: Array[MEntity]): Array[MEntity] do
94 var n
= req
.int_arg
("n")
96 return mentities
.sub
(0, n
)
101 redef fun get
(req
, res
) do
102 var mentities
= list_mentities
(req
)
103 mentities
= sort_mentities
(req
, mentities
)
104 mentities
= limit_mentities
(req
, mentities
)
105 res
.json
new JsonArray.from
(mentities
)
109 # Search mentities from a query string.
111 # Example: `GET /search?q=Arr`
115 redef fun get
(req
, res
) do
116 var query
= req
.string_arg
("q")
117 if query
== null then
118 res
.api_error
(400, "Missing search string")
121 var page
= req
.int_arg
("p")
122 var limit
= req
.int_arg
("n")
123 var response
= new JsonArray.from
(search
(query
, limit
))
124 res
.json paginate
(response
, response
.length
, page
, limit
)
127 fun search
(query
: String, limit
: nullable Int): Array[MEntity] do
128 return config
.view
.find
(query
)
132 # Return a random list of MEntities.
134 # Example: `GET /random?n=10&k=module`
138 # Randomize mentities order.
139 fun randomize_mentities
(req
: HttpRequest, mentities
: Array[MEntity]): Array[MEntity] do
140 var res
= mentities
.to_a
145 redef fun get
(req
, res
) do
146 var mentities
= list_mentities
(req
)
147 mentities
= filter_mentities
(req
, mentities
)
148 mentities
= randomize_mentities
(req
, mentities
)
149 mentities
= limit_mentities
(req
, mentities
)
150 res
.json
new JsonArray.from
(mentities
)
154 # Return the JSON representation of a MEntity.
156 # Example: `GET /entity/core::Array`
160 redef fun get
(req
, res
) do
161 var mentity
= mentity_from_uri
(req
, res
)
162 if mentity
== null then return
163 res
.raw_json mentity
.to_full_json
(config
.view
.mainmodule
)
167 # Return the full MDoc of a MEntity.
169 # Example: `GET /entity/core::Array/doc`
173 redef fun get
(req
, res
) do
174 var mentity
= mentity_from_uri
(req
, res
)
175 if mentity
== null then return
177 var obj
= new JsonObject
178 var mdoc
= mentity
.mdoc_or_fallback
180 obj
["documentation"] = mdoc
.html_documentation
.write_to_string
181 obj
["location"] = mdoc
.location
187 # List ancestors, parents, child and descendants of MEntity
189 # Example: `GET /entity/core::Array/inheritance`
190 class APIEntityInheritance
193 redef fun get
(req
, res
) do
194 var mentity
= mentity_from_uri
(req
, res
)
195 if mentity
== null then return
196 res
.json mentity
.hierarchy_poset
(config
.view
)[mentity
]
200 # Linearize super definitions of a MClassDef or a MPropDef if any.
202 # Example: `GET /entity/core::Array/linearization`
203 class APIEntityLinearization
206 redef fun get
(req
, res
) do
207 var mentity
= mentity_from_uri
(req
, res
)
208 if mentity
== null then return
209 var lin
= mentity
.collect_linearization
(config
.mainmodule
)
211 res
.api_error
(404, "No linearization for mentity `{mentity.full_name}`")
214 var mentities
= new JsonArray
215 for e
in lin
do mentities
.add e
220 # List definitions of a MEntity.
222 # Example: `GET /defs/core::Array`
226 redef fun get
(req
, res
) do
227 var mentity
= mentity_from_uri
(req
, res
)
228 if mentity
== null then return
229 var mentities
= new Array[MEntity]
230 if mentity
isa MPackage then
231 mentities
.add_all mentity
.collect_mgroups
(config
.view
)
232 mentities
.add_all mentity
.collect_mmodules
(config
.view
)
233 else if mentity
isa MGroup then
234 mentities
.add_all mentity
.collect_mgroups
(config
.view
)
235 mentities
.add_all mentity
.collect_mmodules
(config
.view
)
236 else if mentity
isa MModule then
237 mentities
.add_all mentity
.collect_local_mclassdefs
(config
.view
)
238 else if mentity
isa MClass then
239 mentities
.add_all mentity
.collect_mclassdefs
(config
.view
)
240 else if mentity
isa MClassDef then
241 mentities
.add_all mentity
.collect_mpropdefs
(config
.view
)
242 else if mentity
isa MProperty then
243 mentities
.add_all mentity
.collect_mpropdefs
(config
.view
)
245 res
.api_error
(404, "No definition list for mentity `{mentity.full_name}`")
248 mentities
= filter_mentities
(req
, mentities
)
249 mentities
= sort_mentities
(req
, mentities
)
250 mentities
= limit_mentities
(req
, mentities
)
251 res
.json
new JsonArray.from
(mentities
)
255 abstract class SVGHandler
258 # Render a `dot` string as a svg image.
259 fun render_dot
(dot
: Text): String do
260 var proc
= new ProcessDuplex("dot", "-Tsvg")
261 var svg
= proc
.write_and_read
(dot
)
268 # Return a UML representation of MEntity.
270 # Example: `GET /entity/core::Array/uml`
274 redef fun get
(req
, res
) do
275 var mentity
= mentity_from_uri
(req
, res
)
276 if mentity
== null then return
278 if mentity
isa MClassDef then mentity
= mentity
.mclass
279 if mentity
isa MClass then
280 var uml
= new UMLModel(config
.view
, config
.mainmodule
)
281 dot
= uml
.generate_class_uml
.write_to_string
282 else if mentity
isa MModule then
283 var uml
= new UMLModel(config
.view
, mentity
)
284 dot
= uml
.generate_package_uml
.write_to_string
286 res
.api_error
(404, "No UML for mentity `{mentity.full_name}`")
289 res
.send render_dot
(dot
)
293 # Return the source code of MEntity.
295 # Example: `GET /entity/core::Array/code`
299 redef fun get
(req
, res
) do
300 var mentity
= mentity_from_uri
(req
, res
)
301 if mentity
== null then return
302 var source
= render_source
(mentity
)
303 if source
== null then
304 res
.api_error
(404, "No code for mentity `{mentity.full_name}`")
310 # Highlight `mentity` source code.
311 private fun render_source
(mentity
: MEntity): nullable HTMLTag do
312 var node
= config
.modelbuilder
.mentity2node
(mentity
)
313 if node
== null then return null
314 var hl
= new HighlightVisitor