package components : components = 'platform:/resource/Components/model/components.oclinecore' { class Container { operation extendPaths(currentC : Component, currentP) { body: if currentC.targets->size() = 1 then currentP->select(subset | subset->includes(currentC.sources))->collect(c | c->append(currentC)) else currentP->append(OrderedSet{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 : Component[*] { ordered derived transient volatile } { derivation: self.components->iterate(c; pts : OrderedSet(OrderedSet(Component)) = OrderedSet{OrderedSet{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)); } } }