cmd/cmd_catalog: use filter
[nit.git] / src / doc / commands / commands_catalog.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 # Commands to retrieve Catalog related data
16 module commands_catalog
17
18 import commands_model
19
20 # A DocCommand based on a Catalog
21 abstract class CmdCatalog
22 super DocCommand
23
24 autoinit(model, catalog, filter)
25
26 # Catalog to query at
27 var catalog: Catalog
28 end
29
30 # A CmdSearch command using a Catalog
31 class CmdCatalogSearch
32 super CmdCatalog
33 super CmdSearch
34
35 autoinit(model, catalog, filter, query, limit, page, count, max)
36
37 redef fun init_results do
38 if results != null then return new CmdSuccess
39
40 var res = super
41 if not res isa CmdSuccess then return res
42
43 var query = self.query
44 if query == null then return new ErrorNoQuery
45 sorter = null
46
47 var filter = self.filter
48 var index = model.index
49
50 # lookup by name prefix
51 var matches = index.find_by_name_prefix(query, filter).uniq.
52 sort(lname_sorter, name_sorter, kind_sorter)
53 matches = matches.rerank.sort(vis_sorter, score_sorter)
54
55 # lookup by tags
56 var malus = matches.length
57 if catalog.tag2proj.has_key(query) then
58 for mpackage in catalog.tag2proj[query] do
59 if filter != null and not filter.accept_mentity(mpackage) then continue
60 matches.add new IndexMatch(mpackage, malus)
61 malus += 1
62 end
63 matches = matches.uniq.rerank.sort(vis_sorter, score_sorter)
64 end
65
66 # lookup by full_name prefix
67 malus = matches.length
68 var full_matches = new IndexMatches
69 for match in index.find_by_full_name_prefix(query, filter).
70 sort(lfname_sorter, fname_sorter) do
71 match.score += 1
72 full_matches.add match
73 end
74 matches = matches.uniq
75
76 # lookup by similarity
77 malus = matches.length
78 var sim_matches = new IndexMatches
79 for match in index.find_by_similarity(query, filter).sort(score_sorter, kind_sorter, lname_sorter, name_sorter) do
80 if match.score > query.length then break
81 match.score += 1
82 sim_matches.add match
83 end
84 matches.add_all sim_matches
85 matches = matches.uniq
86 results = matches.rerank.sort(vis_sorter, score_sorter).mentities
87 return res
88 end
89
90 private var score_sorter = new ScoreComparator
91 private var vis_sorter = new VisibilityComparator
92 private var name_sorter = new NameComparator
93 private var lname_sorter = new NameLengthComparator
94 private var fname_sorter = new FullNameComparator
95 private var lfname_sorter = new FullNameLengthComparator
96 private var kind_sorter = new MEntityComparator
97 end
98
99 # Retrieve the catalog metadata for a MPackage
100 class CmdMetadata
101 super CmdEntity
102
103 # MPackage metadata retrieved
104 var metadata: nullable MPackageMetadata = null is optional, writable
105
106 redef fun init_command do
107 if metadata != null then return new CmdSuccess
108
109 var res = super
110 if not res isa CmdSuccess then return res
111 var mentity = self.mentity.as(not null)
112
113 if mentity isa MPackage then
114 metadata = mentity.metadata
115 else
116 return new WarningNoMetadata(mentity)
117 end
118 return res
119 end
120 end
121
122 # No metadata for `mentity`
123 class WarningNoMetadata
124 super CmdWarning
125
126 # MEntity provided
127 var mentity: MEntity
128
129 redef fun to_s do return "No metadata for `{mentity.full_name}`"
130 end
131
132 # Retrieve the packages in the catalog
133 class CmdCatalogPackages
134 super CmdCatalog
135 super CmdEntities
136
137 autoinit(model, catalog, filter, limit, page, count, max)
138
139 redef var sorter = new CatalogScoreSorter(catalog) is lazy
140
141 redef fun init_results do
142 if results != null then return new CmdSuccess
143
144 var res = super
145 if not res isa CmdSuccess then return res
146
147 results = catalog.mpackages.values.to_a
148 return res
149 end
150 end
151
152 # Retrieve the catalog stats
153 class CmdCatalogStats
154 super CmdCatalog
155
156 # Retrieved catalog statistics
157 var stats: nullable CatalogStats = null is optional, writable
158
159 redef fun init_command do
160 super
161 self.stats = catalog.catalog_stats
162 return new CmdSuccess
163 end
164 end
165
166 # Retrieve the catalog tags list
167 class CmdCatalogTags
168 super CmdCatalog
169
170 # Sorter to sort tags alphabetically
171 var tags_sorter = new CatalogTagsSorter is optional, writable
172
173 # Count of packages by tag
174 var packages_count_by_tags: nullable ArrayMap[String, Int] = null is optional, writable
175
176 redef fun init_command do
177 super
178 var tags_to_projects = new ArrayMap[String, Int]
179 var tags = catalog.tag2proj.keys.to_a
180 tags_sorter.sort(tags)
181 for tag in tags do
182 if not catalog.tag2proj.has_key(tag) then continue
183 tags_to_projects[tag] = catalog.tag2proj[tag].length
184 end
185 packages_count_by_tags = tags_to_projects
186 return new CmdSuccess
187 end
188 end
189
190 # Retrieve the packages for a tag
191 class CmdCatalogTag
192 super CmdCatalogPackages
193
194 autoinit(model, catalog, filter, tag, limit, page, count, max)
195
196 # The tag to retrieve
197 var tag: nullable String = null is optional, writable
198
199 redef fun init_command do
200 var tag = self.tag
201 if tag == null then return new ErrorNoTag
202
203 if not catalog.tag2proj.has_key(tag) then return new ErrorTagNotFound(tag)
204 return super
205 end
206
207 redef fun init_results do
208 if results != null then return new CmdSuccess
209
210 var res = super
211 if not res isa CmdSuccess then return res
212
213 results = catalog.tag2proj[tag].to_a
214 return res
215 end
216 end
217
218 # No tag name provided
219 class ErrorNoTag
220 super CmdError
221
222 redef fun to_s do return "No tag name provided"
223 end
224
225 # No tag with this name in the catalog
226 class ErrorTagNotFound
227 super CmdError
228
229 # The tag that was not found
230 var tag: String
231
232 redef fun to_s do return "No tag found for `{tag}`"
233 end
234
235 # Retrieve a person from the catalog
236 class CmdCatalogPerson
237 super CmdCatalog
238
239 # Person to retrieve
240 #
241 # You can also pass a `person_name`.
242 var person: nullable Person = null is optional, writable
243
244 # Name of the person to retrieve
245 #
246 # You can also pass a `person` instance.
247 var person_name: nullable String = null is optional, writable
248
249 # Initialize the `person` result
250 fun init_person: CmdMessage do
251 var person = self.person
252 if person != null then
253 person_name = person.name
254 return new CmdSuccess
255 end
256
257 var name = self.person_name
258 if name == null then return new ErrorNoPerson
259 if not catalog.name2person.has_key(name) then return new ErrorPersonNotFound(name)
260 self.person = catalog.name2person[name]
261 return new CmdSuccess
262 end
263
264 redef fun init_command do
265 init_person
266 return super
267 end
268 end
269
270 # No person instance or name provided
271 class ErrorNoPerson
272 super CmdError
273
274 redef fun to_s do return "No person provided"
275 end
276
277 # No person found with this name
278 class ErrorPersonNotFound
279 super CmdError
280
281 # Name of the person that was not found
282 var name: String
283
284 redef fun to_s do return "No person found for `{name}`"
285 end
286
287 # Retrieve the packages maintained by a person
288 class CmdCatalogMaintaining
289 super CmdCatalogPerson
290 super CmdCatalogPackages
291
292 autoinit(model, catalog, filter, person, person_name, limit, page, count, max)
293
294 redef fun init_command do return super
295
296 redef fun init_results do
297 if results != null then return new CmdSuccess
298 var res = super
299 if not res isa CmdSuccess then return res
300 var person = self.person.as(not null)
301
302 if not catalog.maint2proj.has_key(person) then return res
303 results = catalog.maint2proj[person]
304 return res
305 end
306 end
307
308 # Retrieve the packages contributed by a person
309 class CmdCatalogContributing
310 super CmdCatalogPerson
311 super CmdCatalogPackages
312
313 autoinit(model, catalog, filter, person, person_name, limit, page, count, max)
314
315 # Include maintained packages?
316 #
317 # Default is `false`.
318 var maintaining = false is optional, writable
319
320 # FIXME linearization
321 redef fun init_command do return super
322
323 redef fun init_results do
324 if results != null then return new CmdSuccess
325
326 var res = super
327 if not res isa CmdSuccess then return res
328 var person = self.person.as(not null)
329
330 if not catalog.contrib2proj.has_key(person) then return res
331
332 var maint2proj = null
333 if catalog.maint2proj.has_key(person) then
334 maint2proj = catalog.maint2proj[person]
335 end
336
337 var results = new Array[MPackage]
338 for mpackage in catalog.contrib2proj[person] do
339 if not maintaining and maint2proj != null and maint2proj.has(mpackage) then continue
340 results.add mpackage
341 end
342 self.results = results
343 return res
344 end
345 end