nitweb: use config file
[nit.git] / src / web / web_base.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
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
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14
15 # Base classes used by `nitweb`.
16 module web_base
17
18 import model::model_views
19 import model::model_json
20 import doc_down
21 import popcorn
22 import popcorn::pop_config
23
24 # Nitweb config file.
25 class NitwebConfig
26 super AppConfig
27
28 # Model to use.
29 var model: Model
30
31 # MModule used to flatten model.
32 var mainmodule: MModule
33
34 # Modelbuilder used to access sources.
35 var modelbuilder: ModelBuilder
36 end
37
38 # Specific nitcorn Action that uses a Model
39 class ModelHandler
40 super Handler
41
42 # App config.
43 var config: NitwebConfig
44
45 # Find the MEntity ` with `full_name`.
46 fun find_mentity(model: ModelView, full_name: nullable String): nullable MEntity do
47 if full_name == null then return null
48 return model.mentity_by_full_name(full_name.from_percent_encoding)
49 end
50
51 # Init the model view from the `req` uri parameters.
52 fun init_model_view(req: HttpRequest): ModelView do
53 var view = new ModelView(config.model)
54 var show_private = req.bool_arg("private") or else false
55 if not show_private then view.min_visibility = protected_visibility
56
57 view.include_fictive = req.bool_arg("fictive") or else false
58 view.include_empty_doc = req.bool_arg("empty-doc") or else true
59 view.include_test_suite = req.bool_arg("test-suite") or else false
60 view.include_attribute = req.bool_arg("attributes") or else true
61
62 return view
63 end
64 end
65
66 # Specific handler for nitweb API.
67 abstract class APIHandler
68 super ModelHandler
69
70 # The JSON API does not filter anything by default.
71 #
72 # So we can cache the model view.
73 var view: ModelView is lazy do
74 var view = new ModelView(config.model)
75 view.min_visibility = private_visibility
76 view.include_fictive = true
77 view.include_empty_doc = true
78 view.include_attribute = true
79 view.include_test_suite = true
80 return view
81 end
82
83 # Try to load the mentity from uri with `/:id`.
84 #
85 # Send 400 if `:id` is null.
86 # Send 404 if no entity is found.
87 # Return null in both cases.
88 fun mentity_from_uri(req: HttpRequest, res: HttpResponse): nullable MEntity do
89 var id = req.param("id")
90 if id == null then
91 res.error 400
92 return null
93 end
94 var mentity = find_mentity(view, id)
95 if mentity == null then
96 res.error 404
97 end
98 return mentity
99 end
100 end
101
102 # A Rooter dedicated to APIHandlers.
103 class APIRouter
104 super Router
105
106 # App config.
107 var config: NitwebConfig
108 end
109
110 redef class MEntity
111
112 # URL to `self` within the web interface.
113 fun web_url: String do return "/doc/" / full_name
114
115 # URL to `self` within the JSON api.
116 fun api_url: String do return "/api/entity/" / full_name
117
118 redef fun json do
119 var obj = super
120 obj["web_url"] = web_url
121 obj["api_url"] = api_url
122 return obj
123 end
124
125 # Get the full json repesentation of `self` with MEntityRefs resolved.
126 fun api_json(handler: ModelHandler): JsonObject do return json
127 end
128
129 redef class MEntityRef
130 redef fun json do
131 var obj = super
132 obj["web_url"] = mentity.web_url
133 obj["api_url"] = mentity.api_url
134 obj["name"] = mentity.name
135 obj["mdoc"] = mentity.mdoc_or_fallback
136 obj["visibility"] = mentity.visibility
137 obj["location"] = mentity.location
138 var modifiers = new JsonArray
139 for modifier in mentity.collect_modifiers do
140 modifiers.add modifier
141 end
142 obj["modifiers"] = modifiers
143 var mentity = self.mentity
144 if mentity isa MMethod then
145 obj["msignature"] = mentity.intro.msignature
146 else if mentity isa MMethodDef then
147 obj["msignature"] = mentity.msignature
148 else if mentity isa MVirtualTypeProp then
149 obj["bound"] = to_mentity_ref(mentity.intro.bound)
150 else if mentity isa MVirtualTypeDef then
151 obj["bound"] = to_mentity_ref(mentity.bound)
152 end
153 return obj
154 end
155 end
156
157 redef class MDoc
158
159 # Add doc down processing
160 redef fun json do
161 var obj = super
162 obj["synopsis"] = synopsis
163 obj["documentation"] = documentation
164 obj["comment"] = comment
165 obj["html_synopsis"] = html_synopsis.write_to_string
166 obj["html_documentation"] = html_documentation.write_to_string
167 obj["html_comment"] = html_comment.write_to_string
168 return obj
169 end
170 end
171
172 redef class MModule
173 redef fun api_json(handler) do
174 var obj = super
175 obj["intro_mclassdefs"] = to_mentity_refs(collect_intro_mclassdefs(private_view))
176 obj["redef_mclassdefs"] = to_mentity_refs(collect_redef_mclassdefs(private_view))
177 obj["imports"] = to_mentity_refs(in_importation.direct_greaters)
178 return obj
179 end
180 end
181
182 redef class MClass
183 redef fun api_json(handler) do
184 var obj = super
185 obj["all_mproperties"] = to_mentity_refs(collect_accessible_mproperties(private_view))
186 obj["intro_mproperties"] = to_mentity_refs(collect_intro_mproperties(private_view))
187 obj["redef_mproperties"] = to_mentity_refs(collect_redef_mproperties(private_view))
188 obj["parents"] = to_mentity_refs(collect_parents(private_view))
189 return obj
190 end
191 end
192
193 redef class MClassDef
194 redef fun json do
195 var obj = super
196 obj["intro"] = to_mentity_ref(mclass.intro)
197 obj["mpackage"] = to_mentity_ref(mmodule.mpackage)
198 return obj
199 end
200
201 redef fun api_json(handler) do
202 var obj = super
203 obj["intro_mpropdefs"] = to_mentity_refs(collect_intro_mpropdefs(private_view))
204 obj["redef_mpropdefs"] = to_mentity_refs(collect_redef_mpropdefs(private_view))
205 return obj
206 end
207 end
208
209 redef class MProperty
210 redef fun json do
211 var obj = super
212 obj["intro_mclass"] = to_mentity_ref(intro_mclassdef.mclass)
213 obj["mpackage"] = to_mentity_ref(intro_mclassdef.mmodule.mpackage)
214 return obj
215 end
216 end
217
218 redef class MPropDef
219 redef fun json do
220 var obj = super
221 obj["intro"] = to_mentity_ref(mproperty.intro)
222 obj["intro_mclassdef"] = to_mentity_ref(mproperty.intro.mclassdef)
223 obj["mmodule"] = to_mentity_ref(mclassdef.mmodule)
224 obj["mgroup"] = to_mentity_ref(mclassdef.mmodule.mgroup)
225 obj["mpackage"] = to_mentity_ref(mclassdef.mmodule.mpackage)
226 return obj
227 end
228 end
229
230 redef class MClassType
231 redef var web_url = mclass.web_url is lazy
232 end
233
234 redef class MNullableType
235 redef var web_url = mtype.web_url is lazy
236 end
237
238 redef class MParameterType
239 redef var web_url = mclass.web_url is lazy
240 end
241
242 redef class MVirtualType
243 redef var web_url = mproperty.web_url is lazy
244 end
245
246 redef class POSetElement[E]
247 super Jsonable
248
249 # Return JSON representation of `self`.
250 fun json: JsonObject do
251 assert self isa POSetElement[MEntity]
252 var obj = new JsonObject
253 obj["greaters"] = to_mentity_refs(greaters)
254 obj["direct_greaters"] = to_mentity_refs(direct_greaters)
255 obj["direct_smallers"] = to_mentity_refs(direct_smallers)
256 obj["smallers"] = to_mentity_refs(smallers)
257 return obj
258 end
259
260 redef fun to_json do return json.to_json
261 end