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 # Sort mentities by lexicographic order
75 # TODO choose order from request
76 fun sort_mentities
(req
: HttpRequest, mentities
: Array[MEntity]) : Array[MEntity] do
77 var sorted
= mentities
.to_a
78 var sorter
= new MEntityNameSorter
83 # Limit mentities depending on the `n` parameter.
84 fun limit_mentities
(req
: HttpRequest, mentities
: Array[MEntity]): Array[MEntity] do
85 var n
= req
.int_arg
("n")
87 return mentities
.sub
(0, n
)
92 redef fun get
(req
, res
) do
93 var mentities
= list_mentities
(req
)
94 mentities
= sort_mentities
(req
, mentities
)
95 mentities
= limit_mentities
(req
, mentities
)
96 res
.json
new JsonArray.from
(mentities
)
100 # Search mentities from a query string.
102 # Example: `GET /search?q=Arr`
106 redef fun get
(req
, res
) do
107 var q
= req
.string_arg
("q")
109 res
.json
new JsonArray
112 var n
= req
.int_arg
("n")
113 res
.json
new JsonArray.from
(config
.view
.find
(q
, n
))
117 # Return a random list of MEntities.
119 # Example: `GET /random?n=10&k=module`
123 # Randomize mentities order.
124 fun randomize_mentities
(req
: HttpRequest, mentities
: Array[MEntity]): Array[MEntity] do
125 var res
= mentities
.to_a
130 redef fun get
(req
, res
) do
131 var mentities
= list_mentities
(req
)
132 mentities
= randomize_mentities
(req
, mentities
)
133 mentities
= limit_mentities
(req
, mentities
)
134 res
.json
new JsonArray.from
(mentities
)
138 # Return the JSON representation of a MEntity.
140 # Example: `GET /entity/core::Array`
144 redef fun get
(req
, res
) do
145 var mentity
= mentity_from_uri
(req
, res
)
146 if mentity
== null then return
147 res
.raw_json mentity
.to_full_json
151 # Return the full MDoc of a MEntity.
153 # Example: `GET /entity/core::Array/doc`
157 redef fun get
(req
, res
) do
158 var mentity
= mentity_from_uri
(req
, res
)
159 if mentity
== null then return
161 var obj
= new JsonObject
162 var mdoc
= mentity
.mdoc_or_fallback
164 obj
["documentation"] = mdoc
.html_documentation
.write_to_string
165 obj
["location"] = mdoc
.location
171 # List ancestors, parents, child and descendants of MEntity
173 # Example: `GET /entity/core::Array/inheritance`
174 class APIEntityInheritance
177 redef fun get
(req
, res
) do
178 var mentity
= mentity_from_uri
(req
, res
)
179 if mentity
== null then return
180 res
.json mentity
.hierarchy_poset
(config
.view
)[mentity
]
184 # Linearize super definitions of a MClassDef or a MPropDef if any.
186 # Example: `GET /entity/core::Array/linearization`
187 class APIEntityLinearization
190 redef fun get
(req
, res
) do
191 var mentity
= mentity_from_uri
(req
, res
)
192 if mentity
== null then return
193 var lin
= mentity
.collect_linearization
(config
.mainmodule
)
195 res
.api_error
(404, "No linearization for mentity `{mentity.full_name}`")
198 var mentities
= new JsonArray
199 for e
in lin
do mentities
.add e
204 # List definitions of a MEntity.
206 # Example: `GET /defs/core::Array`
210 redef fun get
(req
, res
) do
211 var mentity
= mentity_from_uri
(req
, res
)
212 if mentity
== null then return
213 var mentities
: Array[MEntity]
214 if mentity
isa MPackage then
215 mentities
= mentity
.mgroups
.to_a
216 else if mentity
isa MGroup then
217 mentities
= new Array[MEntity]
218 mentities
.add_all mentity
.in_nesting
.direct_smallers
219 mentities
.add_all mentity
.mmodules
220 else if mentity
isa MModule then
221 mentities
= mentity
.mclassdefs
222 else if mentity
isa MClass then
223 mentities
= mentity
.mclassdefs
224 else if mentity
isa MClassDef then
225 mentities
= mentity
.mpropdefs
226 else if mentity
isa MProperty then
227 mentities
= mentity
.mpropdefs
229 res
.api_error
(404, "No definition list for mentity `{mentity.full_name}`")
232 mentities
= sort_mentities
(req
, mentities
)
233 mentities
= limit_mentities
(req
, mentities
)
234 res
.json
new JsonArray.from
(mentities
)
238 abstract class SVGHandler
241 # Render a `dot` string as a svg image.
242 fun render_dot
(dot
: Text): String do
243 var proc
= new ProcessDuplex("dot", "-Tsvg")
244 var svg
= proc
.write_and_read
(dot
)
251 # Return a UML representation of MEntity.
253 # Example: `GET /entity/core::Array/uml`
257 redef fun get
(req
, res
) do
258 var mentity
= mentity_from_uri
(req
, res
)
259 if mentity
== null then return
261 if mentity
isa MClassDef then mentity
= mentity
.mclass
262 if mentity
isa MClass then
263 var uml
= new UMLModel(config
.view
, config
.mainmodule
)
264 dot
= uml
.generate_class_uml
.write_to_string
265 else if mentity
isa MModule then
266 var uml
= new UMLModel(config
.view
, mentity
)
267 dot
= uml
.generate_package_uml
.write_to_string
269 res
.api_error
(404, "No UML for mentity `{mentity.full_name}`")
272 res
.send render_dot
(dot
)
276 # Return the source code of MEntity.
278 # Example: `GET /entity/core::Array/code`
282 redef fun get
(req
, res
) do
283 var mentity
= mentity_from_uri
(req
, res
)
284 if mentity
== null then return
285 var source
= render_source
(mentity
)
286 if source
== null then
287 res
.api_error
(404, "No code for mentity `{mentity.full_name}`")
293 # Highlight `mentity` source code.
294 private fun render_source
(mentity
: MEntity): nullable HTMLTag do
295 var node
= config
.modelbuilder
.mentity2node
(mentity
)
296 if node
== null then return null
297 var hl
= new HighlightVisitor