Merge: Reworked crypto.nit to introduce basic XOR attacks
[nit.git] / src / model / model_views.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 module model_views
16
17 import model_visitor
18
19 # Provide a configurable view to a model.
20 #
21 # This can be useful when you need to filter some mentities from a model
22 # like private or fictive.
23 #
24 # TODO doc usage
25 class ModelView
26 super ModelVisitor
27
28 # The model to view through `self`.
29 var model: Model
30
31 # MPackages visible through `self`.
32 var mpackages: Set[MPackage] is lazy do
33 var mpackages = new HashSet[MPackage]
34 for mpackage in model.mpackages do
35 if not accept_mentity(mpackage) then continue
36 mpackages.add mpackage
37 end
38 return mpackages
39 end
40
41 # MGroups visible through `self`.
42 var mgroups: Set[MGroup] is lazy do
43 var mgroups = new HashSet[MGroup]
44 for mpackage in mpackages do
45 for mgroup in mpackage.mgroups do
46 if not accept_mentity(mgroup) then continue
47 mgroups.add mgroup
48 end
49 end
50 return mgroups
51 end
52
53 # MModules visible through `self`.
54 var mmodules: Set[MModule] is lazy do
55 var mmodules = new HashSet[MModule]
56 for mmodule in model.mmodules do
57 if not accept_mentity(mmodule) then continue
58 mmodules.add mmodule
59 end
60 return mmodules
61 end
62
63 # MClasses visible through `self`.
64 var mclasses: Set[MClass] is lazy do
65 var mclasses = new HashSet[MClass]
66 for mclass in model.mclasses do
67 if not accept_mentity(mclass) then continue
68 mclasses.add mclass
69 end
70 return mclasses
71 end
72
73 # MClassDefs visible through `self`.
74 var mclassdefs: Set[MClassDef] is lazy do
75 var mclassdefs = new HashSet[MClassDef]
76 for mclass in mclasses do
77 for mclassdef in mclass.mclassdefs do
78 if not accept_mentity(mclassdef) then continue
79 mclassdefs.add mclassdef
80 end
81 end
82 return mclassdefs
83 end
84
85 # MProperties visible through `self`.
86 var mproperties: Set[MProperty] is lazy do
87 var mproperties = new HashSet[MProperty]
88 for mproperty in model.mproperties do
89 if not accept_mentity(mproperty) then continue
90 mproperties.add mproperty
91 end
92 return mproperties
93 end
94
95 # MPropdefs visible through `self`.
96 var mpropdefs: Set[MPropDef] is lazy do
97 var mpropdefs = new HashSet[MPropDef]
98 for mproperty in mproperties do
99 for mpropdef in mproperty.mpropdefs do
100 if not accept_mentity(mpropdef) then continue
101 mpropdefs.add mpropdef
102 end
103 end
104 return mpropdefs
105 end
106
107 # Lists all MEntities visible through `self`.
108 var mentities: Set[MEntity] is lazy do
109 var res = new HashSet[MEntity]
110 res.add_all mpackages
111 res.add_all mgroups
112 res.add_all mmodules
113 res.add_all mclasses
114 res.add_all mclassdefs
115 res.add_all mproperties
116 res.add_all mpropdefs
117 return res
118 end
119
120 private fun init_visitor(v: ModelVisitor) do
121 v.min_visibility = self.min_visibility
122 v.include_fictive = self.include_fictive
123 v.include_empty_doc = self.include_empty_doc
124 v.include_attribute = self.include_attribute
125 v.include_test_suite = self.include_test_suite
126 end
127
128 # Searches MEntities that match `name`.
129 fun mentities_by_name(name: String): Array[MEntity] do
130 var res = new Array[MEntity]
131 for mentity in mentities do if mentity.name == name then res.add mentity
132 return res
133 end
134
135 # Searches the MEntity that matches `full_name`.
136 fun mentity_by_full_name(full_name: String): nullable MEntity do
137 for mentity in mentities do
138 if mentity.full_name == full_name then return mentity
139 end
140 return null
141 end
142
143 # Looks up a MEntity by its full `namespace`.
144 #
145 # Usefull when `mentities_by_name` returns conflicts.
146 #
147 # Namespaces must be of the form `package::core::module::Class::prop`.
148 fun mentities_by_namespace(namespace: String): Array[MEntity] do
149 var v = new LookupNamespaceVisitor(namespace)
150 init_visitor(v)
151 for mpackage in mpackages do
152 v.enter_visit(mpackage)
153 end
154 return v.results
155 end
156
157 # Build an concerns tree with from `self`
158 fun to_tree: MEntityTree do
159 var v = new ModelTreeVisitor
160 init_visitor(v)
161 for mpackage in mpackages do
162 v.enter_visit(mpackage)
163 end
164 return v.tree
165 end
166
167 # Build the POSet of `mmodules` importation.
168 fun mmodules_poset(mmodules: Set[MModule]): POSet[MModule] do
169 return model.mmodule_importation_hierarchy.sub(mmodules)
170 end
171
172 # Build the POSet of `mmodules` hierarchy.
173 fun mclasses_poset(mainmodule: MModule, mclasses: Set[MClass]): POSet[MClass] do
174 return mainmodule.flatten_mclass_hierarchy.sub(mclasses)
175 end
176 end
177
178 class LookupNamespaceVisitor
179 super ModelVisitor
180
181 var namespace: String
182
183 private var parts: Array[String] is lazy do return namespace.split_with("::")
184
185 var results = new Array[MEntity]
186
187 redef fun visit(mentity) do mentity.accept_namespace_visitor(self)
188 end
189
190 class ModelTreeVisitor
191 super ModelVisitor
192
193 var tree = new MEntityTree
194
195 redef fun visit(mentity) do mentity.accept_tree_visitor(self)
196 end
197
198 redef class MEntity
199
200 # Get a public view of the model
201 fun public_view: ModelView do
202 var view = new ModelView(self.model)
203 view.min_visibility = public_visibility
204 return view
205 end
206
207 # Get a public view of the model
208 fun protected_view: ModelView do
209 var view = new ModelView(self.model)
210 view.min_visibility = protected_visibility
211 return view
212 end
213
214 # Get a public view of the model
215 fun private_view: ModelView do
216 var view = new ModelView(self.model)
217 view.min_visibility = private_visibility
218 return view
219 end
220
221 private fun accept_namespace_visitor(v: LookupNamespaceVisitor) do
222 if v.parts.is_empty then return
223 if name != v.parts.first then return
224 v.parts.shift
225 if v.parts.is_empty then
226 v.results.add self
227 return
228 end
229 visit_all(v)
230 end
231
232 private fun accept_tree_visitor(v: ModelTreeVisitor) do end
233 end
234
235 redef class MPackage
236 redef fun accept_tree_visitor(v) do
237 v.tree.add(null, self)
238 visit_all(v)
239 end
240 end
241
242 redef class MGroup
243 redef fun accept_tree_visitor(v) do
244 var parent = self.parent
245 if parent != null then
246 v.tree.add(parent, self)
247 else
248 v.tree.add(mpackage, self)
249 end
250 visit_all(v)
251 end
252 end
253
254 redef class MModule
255 redef fun accept_tree_visitor(v) do
256 v.tree.add(mgroup, self)
257 visit_all(v)
258 end
259 end
260
261 redef class MClass
262 # We don't want to collect classes from full namespace.
263 redef fun accept_namespace_visitor(v) do end
264 end
265
266 redef class MClassDef
267 redef fun accept_tree_visitor(v) do
268 v.tree.add(mmodule, self)
269 visit_all(v)
270 end
271 end
272
273 redef class MProperty
274 # We don't want to collect properties from full namespace.
275 redef fun accept_namespace_visitor(v) do end
276 end
277
278 redef class MPropDef
279 redef fun accept_tree_visitor(v) do
280 v.tree.add(mclassdef, self)
281 visit_all(v)
282 end
283 end