package components : components = 'platform:/resource/Components/model/components.oclinecore' { class Container { operation extendPaths(currentC : Component, currentP : Path[*]) : Path[*] { body: if currentC.targets->size() = 1 then currentP->select(subset | )->collect(c | c.append(currentC)) else currentP->asOrderedSet()->append(createPath(currentC)) endif; } property components : Component[*] { ordered composes }; property firstComponent : Component; property lastComponent : Component; attribute requiredNumPaths : Integer; attribute numPaths : Integer { derived transient volatile } { derivation: self.components->reject(c | c = lastComponent)->iterate(c; numPaths : Integer = 1 | numPaths + c.targets->size() - 1); } property paths : Path[*] { ordered derived transient volatile } { derivation: self.components->iterate(c; pts : OrderedSet(Path) = OrderedSet{createPath(firstComponent)} | extendPaths(c, pts)); } invariant numpathsinv: numPaths = requiredNumPaths; invariant firstComponent0Sources: self.firstComponent.sources->size() = 0; invariant lastComponent0Targets: self.lastComponent.targets->size() = 0; } class Component { attribute name : String[?]; property targets#sources : Component[*] { ordered }; property sources#targets : Component[*] { ordered }; property followers : Component[*] { ordered derived transient volatile } { derivation: self.targets->union(self.targets->closure(targets)); } } class Path { operation append(c : Component) : Path { body: self.components->append(c); } operation createPath(c : Component) : Path { body: ; } property components : Component[*] { ordered }; } }