+redef class MEntity
+
+ # FIXME used to bypass RTA limitation on type resolution
+ type MENTITY: SELF
+
+ # Collect modifier keywords like `redef`, `private` etc
+ fun collect_modifiers: Array[String] do return new Array[String]
+
+ # Collect `self` linearization anchored on `mainmodule`
+ fun collect_linearization(mainmodule: MModule): nullable Array[MEntity] do
+ return null
+ end
+
+ # Collect `self` ancestors (direct and indirect)
+ #
+ # The concept of ancestor is abstract at this stage.
+ fun collect_ancestors(view: ModelView): Set[MENTITY] do
+ var done = new HashSet[MENTITY]
+ var todo = new Array[MENTITY]
+
+ todo.add_all collect_parents(view)
+ while todo.not_empty do
+ var mentity = todo.pop
+ if mentity == self or done.has(mentity) then continue
+ done.add mentity
+ todo.add_all mentity.collect_parents(view)
+ end
+ return done
+ end
+
+ # Collect `self` parents (direct ancestors)
+ #
+ # The concept of parent is abstract at this stage.
+ fun collect_parents(view: ModelView): Set[MENTITY] is abstract
+
+ # Collect `self` children (direct descendants)
+ #
+ # The concept of child is abstract at this stage.
+ fun collect_children(view: ModelView): Set[MENTITY] is abstract
+
+ # Collect `self` descendants (direct and direct)
+ #
+ # The concept of descendant is abstract at this stage.
+ fun collect_descendants(view: ModelView): Set[MENTITY] do
+ var done = new HashSet[MENTITY]
+ var todo = new Array[MENTITY]
+
+ todo.add_all collect_children(view)
+ while todo.not_empty do
+ var mentity = todo.pop
+ if mentity == self or done.has(mentity) then continue
+ done.add mentity
+ todo.add_all mentity.collect_children(view)
+ end
+ return done
+ end
+
+ # Build a poset representing `self` in it's own hierarchy
+ #
+ # The notion of hierarchy depends on the type of MEntity.
+ #
+ # Here a recap:
+ # * `MPackage`: package dependencies
+ # * `MGroup`: group dependencies
+ # * `MModule`: modules imports
+ # * `MClass`: class inheritance (all classdefs flattened)
+ # * `MClassDef`: classdef inheritance
+ # * `MProperty`: property definitions graph (all propdefs flattened)
+ # * `MPropDef`: property definitions graph
+ fun hierarchy_poset(view: ModelView): POSet[MENTITY] do
+ var done = new HashSet[MENTITY]
+ var mentities = new Array[MENTITY]
+ mentities.add self
+ var poset = new POSet[MENTITY]
+ while mentities.not_empty do
+ var mentity = mentities.pop
+ if done.has(mentity) then continue
+ done.add mentity
+ poset.add_node mentity
+ for parent in mentity.collect_parents(view) do
+ poset.add_edge(mentity, parent)
+ mentities.add parent
+ end
+ for child in mentity.collect_children(view) do
+ poset.add_edge(child, mentity)
+ mentities.add child
+ end
+ end
+ return poset
+ end
+end
+
+redef class Model
+
+ # Collect all MPackages in `self`
+ fun collect_mpackages(view: ModelView): HashSet[MPackage] do
+ var res = new HashSet[MPackage]
+ for mpackage in mpackages do
+ if not view.accept_mentity(mpackage) then continue
+ res.add(mpackage)
+ end
+ return res
+ end
+
+ # Collect all MModules in `self`
+ fun collect_mmodules(view: ModelView): HashSet[MModule] do
+ var res = new HashSet[MModule]
+ for mpackage in collect_mpackages(view) do
+ res.add_all mpackage.collect_all_mmodules(view)
+ end
+ return res
+ end
+
+ # Collect all MClasses introduced in `self`
+ fun collect_intro_mclasses(view: ModelView): HashSet[MClass] do
+ var res = new HashSet[MClass]
+ for mpackage in collect_mpackages(view) do
+ res.add_all mpackage.collect_intro_mclasses(view)
+ end
+ return res
+ end
+
+ # Collect all MProperties introduced in `self`
+ fun collect_intro_mproperties(view: ModelView): HashSet[MProperty] do
+ var res = new HashSet[MProperty]
+ for mpackage in collect_mpackages(view) do
+ res.add_all mpackage.collect_intro_mproperties(view)
+ end
+ return res
+ end
+end
+
+redef class MPackage
+
+ redef fun collect_modifiers do return super + ["package"]
+
+ # Collect all packages directly imported by `self`
+ redef fun collect_parents(view) do
+ var res = new HashSet[MENTITY]
+ for mgroup in mgroups do
+ for parent in mgroup.collect_parents(view) do
+ var mpackage = parent.mpackage
+ if mpackage == self or not view.accept_mentity(mpackage) then continue
+ res.add(mpackage)
+ end
+ end
+ return res
+ end
+
+ # Collect all packages that directly depends on `self`
+ redef fun collect_children(view) do
+ var res = new HashSet[MENTITY]
+ for mpackage in view.mpackages do
+ if mpackage.collect_parents(view).has(self) then res.add mpackage
+ end
+ return res
+ end
+
+ # Collect all groups contained in `self`
+ fun collect_all_mgroups(view: ModelView): HashSet[MGroup] do
+ var res = new HashSet[MGroup]
+ for mgroup in mgroups do
+ if not view.accept_mentity(mgroup) then continue
+ res.add(mgroup)
+ end
+ return res
+ end
+
+ # Collect only groups contained in `self.root`
+ fun collect_mgroups(view: ModelView): HashSet[MGroup] do
+ var res = new HashSet[MGroup]
+ var root = self.root
+ if root == null then return res
+ res.add_all root.collect_mgroups(view)
+ return res
+ end
+
+ # Collect all modules contained in `self`
+ fun collect_all_mmodules(view: ModelView): HashSet[MModule] do
+ var res = new HashSet[MModule]
+ for mgroup in collect_mgroups(view) do
+ res.add_all mgroup.collect_mmodules(view)
+ end
+ return res
+ end
+
+ # Collect only modules contained in `self.root`
+ fun collect_mmodules(view: ModelView): HashSet[MModule] do
+ var res = new HashSet[MModule]
+ var root = self.root
+ if root == null then return res
+ res.add_all root.collect_mmodules(view)
+ return res
+ end
+
+ # Collect all classes introduced in `self`
+ fun collect_intro_mclasses(view: ModelView): HashSet[MClass] do
+ var res = new HashSet[MClass]
+ for mgroup in mgroups do
+ for mmodule in collect_all_mmodules(view) do
+ res.add_all mmodule.collect_intro_mclasses(view)
+ end
+ end
+ return res
+ end
+
+ # Collect all classes redefined or refined in `self`
+ fun collect_redef_mclasses(view: ModelView): Set[MClass] do
+ var res = new HashSet[MClass]
+ for mgroup in mgroups do
+ for mmodule in collect_all_mmodules(view) do
+ res.add_all mmodule.collect_redef_mclasses(view)
+ end
+ end
+ return res
+ end
+
+ # Collect all properties introduced in `self`
+ fun collect_intro_mproperties(view: ModelView): HashSet[MProperty] do
+ var res = new HashSet[MProperty]
+ for mgroup in mgroups do
+ for mmodule in collect_all_mmodules(view) do
+ res.add_all mmodule.collect_intro_mproperties(view)
+ end
+ end
+ return res
+ end
+
+ # Collect all properties redefined in `self`
+ fun collect_redef_mproperties(view: ModelView): HashSet[MProperty] do
+ var res = new HashSet[MProperty]
+ for mgroup in mgroups do
+ for mmodule in collect_all_mmodules(view) do
+ res.add_all mmodule.collect_redef_mproperties(view)
+ end
+ end
+ return res
+ end
+
+ # Collect all attributes introduced in `self`
+ fun collect_intro_attributes(view: ModelView): Set[MAttribute] do
+ var res = new HashSet[MAttribute]
+ for mgroup in mgroups do
+ for mmodule in collect_all_mmodules(view) do
+ res.add_all mmodule.collect_intro_attributes(view)
+ end
+ end
+ return res
+ end
+
+ # Collect all inits introduced in `self`
+ fun collect_intro_inits(view: ModelView): Set[MMethod] do
+ var res = new HashSet[MMethod]
+ for mgroup in mgroups do
+ for mmodule in collect_all_mmodules(view) do
+ res.add_all mmodule.collect_intro_inits(view)
+ end
+ end
+ return res
+ end
+
+ # Collect all methods introduced in `self` excluding inits
+ #
+ # See `collect_intro_inits`.
+ fun collect_intro_methods(view: ModelView): Set[MMethod] do
+ var res = new HashSet[MMethod]
+ for mgroup in mgroups do
+ for mmodule in collect_all_mmodules(view) do
+ res.add_all mmodule.collect_intro_methods(view)
+ end
+ end
+ return res
+ end