
c77b9e97919fd388050bdd2eb415c074.ppt
- Количество слайдов: 102
OCL – Object Constraint Language (OCL version 2. 0) OCL – Object Constraint Language, João Pascoal Faria, October 2007 1
Contents n Introduction n Quick reference: types, operations and expressions n Defining invariants n Defining pre and post-conditions n Other uses n Tools n Exercises, assignments and references n Appendix A: Using UML and OCL in requirements analysis (in Portuguese) n Appendix B: A Hotel Management System example (in Portuguese) n Appendix C: The Stack example with the USE tool OCL – Object Constraint Language, João Pascoal Faria, October 2007 2
Introduction to OCL – Object Constraint Language, João Pascoal Faria, October 2007 3
What is the OCL? n The Object Constraint Language (OCL) is a formal language used to describe expressions in UML models • These expressions typically specify constraints that must hold for the system being modeled or queries over objects described in a model n OCL is a pure specification language; therefore, an OCL expression is guaranteed to be without side effects • When an OCL expression is evaluated, it simply returns a value. It cannot change anything in the model. • The state of the system will never change because of the evaluation of an OCL expression, even though an OCL expression can be used to specify a state change (e. g. , in a post-condition) • OCL is not a programming language; therefore, it is not possible to write program logic or flow control in OCL – Object Constraint Language, João Pascoal Faria, October 2007 4
Where does OCL come from? n n n OCL is part of the UML standard OCL was developed at IBM by Jos Warmer as a language for specifying business rules It has its roots in traditional formal specification languages, such as VDM and Z, but doesn’t require the strong mathematical background usually associated with them • OCL was designed to be easy to read and write n The UML meta-model itself is formally specified with OCL – Object Constraint Language, João Pascoal Faria, October 2007 5
Where to use OCL? n n To specify invariants on classes and types in the class model To specify pre-conditions and post-conditions on Operations and Methods n To specify guards in state machines n To specify derivation rules for derived attributes n To specify initial attribute values n As a generic object query language OCL – Object Constraint Language, João Pascoal Faria, October 2007 6
Why OCL? n Provides a way to develop more precise and semantically rich models using UML • Formal specifications of state constraints with invariants • Formal specification of the semantic of operations with pre and postconditions • Etc. n Better specification • Formal OCL specifications remove the ambiguity that is present in natural language specifications • Formal OCL specifications are verifiable by machines n Better documentation n Implementation free • OCL constraints specify what must be true not what must be done • Evaluating an OCL constraints does not change the state of the system OCL – Object Constraint Language, João Pascoal Faria, October 2007 7
An introductory example Stack T - elements: Sequence(T) - capacity: Integer + + Stack(c: Integer) push(x: T) pop() top(): T context Stack(T) inv: capacity > 0 inv: elements->size() <= capacity context Stack(T): : Stack(c : Integer) pre: c > 0 post: elements->is. Empty() post: capacity = c context Stack(T): : push(x: T) pre: elements->size() < capacity post: elements = elements@pre->append(x) context Stack(T): : pop() pre: elements->not. Empty() post: elements@pre = elements->append(elements@pre->last) context Stack(T): : top() : T pre: elements->not. Empty() post: result = elements->last OCL – Object Constraint Language, João Pascoal Faria, October 2007 8
OCL quick reference: types, operations and expressions OCL – Object Constraint Language, João Pascoal Faria, October 2007 9
OCL types n Predefined types • Primitive types: String, Integer, Real, Boolean • Collection types: Set, Bag, Sequence, Ordered. Set • Tuple types: Tuple • Special types: Ocl. Type, Ocl. Any, … n User-defined model types • User defined classes such as Customer, Date, etc. OCL – Object Constraint Language, João Pascoal Faria, October 2007 10
Primitive types Type Description Integer A whole number of any size Operators and Operations true, false Boolean Values =, <>, and, or, xor, not, implies, if-then-else-endif (note 2) -1, 0, 1, =, <>, >, <, >=, <=, *, +, - (unary), - (binary), … / (real), abs(), max(b), min(b), mod(b), div(b) Real A real number of any size 1. 5, … =, <>, >, <, >=, <=, *, +, - (unary), - (binary), /, abs(), max(b), min(b), round(), floor() String A string of characters 'a', 'John' =, <>, size(), concat(s 2), substring(lower, upper) (1<=lower<=upper<=size), to. Real(), to. Integer() Notes: 1) Operations indicated with parenthesis are applied with “. ”, but the parenthesis may be omitted. 2) Example: title = (if is. Male then 'Mr. ' else 'Ms. ' endif) OCL – Object Constraint Language, João Pascoal Faria, October 2007 11
Collections and tuples Description Abstract collection of elements of type T Unordered collection, no duplicates Ordered collection, duplicates allowed Ordered collection, no duplicates Unordered collection, duplicates allowed Tuple (with named parts) Syntax Examples Collection(T) Set{1 , 2} Sequence(T) Sequence {1, 2, 1} Sequence {1. . 4} (same as {1, 2, 3, 4}) Ordered. Set(T) Ordered. Set {2, 1} Bag(T) Bag {1, 1, 2} Tuple(field 1: T 1, … fieldn : Tn) Tuple {age: Integer = 5, name: String = 'Joe‘ } Tuple {name = 'Joe', age = 5} Note 1: They are value types: “=” and “<>” compare values and not references. Note 2: Tuple components can be accessed with “. ” as in “t 1. name” OCL – Object Constraint Language, João Pascoal Faria, October 2007 12
Operations on Collection(T) Operation Description size(): Integer The number of elements in this collection (self) is. Empty(): Boolean size = 0 not. Empty(): Boolean size > 0 includes(object: T): Boolean True if object is an element of self excludes(object: T): Boolean True if object is not an element of self count(object: T): Integer The number of occurrences of object in self includes. All(c 2: Collection(T)): True if self contains all the elements of c 2 Boolean excludes. All(c 2: Collection(T)): Boolean True if self contains none of the elements of c 2 sum(): T The addition of all elements in self (T must support “+”) product(c 2: Collection(T 2)) : The cartesian product operation of self and c 2. Set(Tuple(first: T, second: T 2)) Note: Operations on collections are applied with “->” and not “. ” OCL – Object Constraint Language, João Pascoal Faria, October 2007 13
Iterator expressions on Collection(T) (1/2) Iterator expression Description iterate(iterator: T; accum: T 2 = init | body) : T 2 Returns the final value of an accumulator that, after initialization, is updated with the value of the body expression for every element in the source collection. exists(iterators | body) : Boolean True if body evaluates to true for at least one element in the source collection. Allows multiple iterator variables. for. All(iterators | body): Boolean True if body evaluates to true for each element in the source collection. Allows multiple iterator variables. one(iterator| body): True if there is exactly one element in the source Boolean collection for which body is true is. Unique(iterator| body): Boolean Results in true if body evaluates to a different value for each element in the source collection. any(iterator | body): Returns any element in the source collection for which T body evaluates to true. The result is null if there is none. collect(iterator| The Collection of elements resulting from applying body to body): Collection(T 2) every member of the source set. The result is flattened. Note: The iterator variable declaration can be omitted when there is no ambiguity. OCL – Object Constraint Language, João Pascoal Faria, October 2007 14
Iterator expressions on Collection(T) (2/2) Iterator expression Description select(iterator | body): Collection(T) The Collection of elements of the source collection for which body is true. The result collection is of the same type of the source collection. reject(iterator | body): Collection(T) The Collection of elements of the source collection for which body is false. The result collection is of the same type of the source collection. collect. Nested(iterator | body): Collection. With. Duplicates(T 2 ) The Collection of elements (allowing duplicates) that results from applying body (of type T 2) to every member of the source collection. The result is not flattened. Conversions: Set -> Bag, Ordered. Set -> Sequence. sorted. By(iterator | body): Ordered. Collection(T) Returns an ordered Collection of all the elements of the source collection by ascending order of the value of the body expression. The type T 2 of the body expression must support “<”. Conversions: Set -> Ordered. Set, Bag -> Sequence. OCL – Object Constraint Language, João Pascoal Faria, October 2007 15
Examples n The following are equivalent: • context Customer inv: Customer. all. Instances->is. Unique(number) • context Customer inv: Customer. all. Instances->for. All(c 1, c 2 | c 1 <> c 2 implies c 1. number <> c 2. number) • context Customer inv: not Customer. all. Instances->iterate(c 1 : Customer ; dup : Boolean = false | dup or (c <> self and c. number = self. number)) n SQL-like example: • context Customer inv: total. Debits = movements->select(m | m. type = debit)->collect(value)->sum() • SQL: select sum(value) from movements where type = debit OCL – Object Constraint Language, João Pascoal Faria, October 2007 16
Operations on Set(T) (1/2) Operation Description =(s: Set(T)) : Boolean Do self and s contain the same elements? union(s: Set(T)): Set(T) The union of self and s. union(b: Bag(T)): Bag(T) The union of self and bag b. intersection(s: Set(T)): Set(T) The intersection of self and s. intersection(b: Bag(T)): Set(T) The intersection of self and b. -(s: Set(T)) : Set(T) The elements of self, which are not in s. including(object: T): Set(T) The set containing all elements of self plus object. excluding(object: T): Set(T) The set containing all elements of self minus object. symmetric. Difference(s: Set(T)): The set containing all the elements that are Set(T) in self or s, but not in both. OCL – Object Constraint Language, João Pascoal Faria, October 2007 17
Operations on Set(T) (2/2) Operation Description flatten() : Set(T 2) If T is a collection type, the result is the set with all the elements of self; otherwise, the result is self. as. Ordered. Set(): Ordered. Set(T) Ordered. Set with elements from self in undefined order. as. Sequence(): Sequence(T) Sequence with elements from self in undefined order. as. Bag(): Bag(T) Bag will all the elements from self. OCL – Object Constraint Language, João Pascoal Faria, October 2007 18
Operations on Bag(T) Operation Description =(bag: Bag(T)) : Boolean True if self and bag contain the same elements, the same number of times. union(bag: Bag(T)): Bag(T) The union of self and bag. union(set: Set(T)): Bag(T) The union of self and set. intersection(bag: Bag(T)): Bag(T) The intersection of self and bag. intersection(set: Set(T)): Set(T) The intersection of self and set. including(object: T): Bag(T) The bag with all elements of self plus object. excluding(object: T): Bag(T) The bag with all elements of self without object. flatten() : Bag(T 2) If T is a collection type: bag with all the elements of self; otherwise: self. as. Sequence(): Sequence(T) Seq. with elements from self in undefined order. as. Set(): Set(T) Set with elements from self, without duplicates. as. Ordered. Set(): Ordered. Set(T) Ordered. Set with elements from self in undefined order, without duplicates. OCL – Object Constraint Language, João Pascoal Faria, October 2007 19
Operations on Sequence(T) (1/2) Operation Description =(s: Sequence(T)) : Boolean True if self contains the same elements as s, in the same order. union(s: Sequence(T)): Sequence(T) The sequence consisting of all elements in self, followed by all elements in s. flatten() : Sequence(T 2) If T is a collection type, the result is the set with all the elements of self; otherwise, it’s self. append(object: T): Sequence(T) The sequence with all elements of self, followed by object. prepend(obj: T): Sequence(T) The sequence with object, followed by all elements in self. insert. At(index : Integer, The sequence consisting of self with object inserted at object : T) : Sequence(T) position index (1<=index<=size+1) sub. Sequence(lower : The sub-sequence of self starting at index lower, up to Integer, upper: Integer) : and including index upper (1<=lower<=upper<=size) Sequence(T) OCL – Object Constraint Language, João Pascoal Faria, October 2007 20
Operations on Sequence(T) (2/2) Operation Description at(i : Integer) : T The i-th element of self (1<=i<=size) index. Of(object : T) : Integer The index of object in self. first() : T The first element in self. last() : T The last element in self. including(object: T): Sequence(T) The sequence containing all elements of self plus object added as last element excluding(object: T): Sequence(T) The sequence containing all elements of self apart from all occurrences of object. as. Bag(): Bag(T) The Bag containing all the elements from self, including duplicates. as. Set(): Set(T) The Set containing all the elements from self, with duplicates removed. as. Ordered. Set(): Ordered. Set(T) An Ordered. Set that contains all the elements from self, in the same order, with duplicates removed. OCL – Object Constraint Language, João Pascoal Faria, October 2007 21
Operations on Ordered. Set(T) Operation Description append(object: T): Ordered. Set(T) The set of elements, consisting of all elements of self, followed by object. prepend(object: T): Ordered. Set(T) The sequence consisting of object, followed by all elements in self. insert. At(index : Integer, object : T) : Ordered. Set(T) The set consisting of self with object inserted at position index. sub. Ordered. Set(lower : Integer, upper : Integer) : Ordered. Set(T) The sub-set of self starting at number lower, up to and including element number upper (1<=lower<=upper<=size). at(i : Integer) : T The i-th element of self (1<=i<=size). index. Of(object : T) : Integer The index of object in the sequence. first() : T The first element in self. last() : T The last element in self. OCL – Object Constraint Language, João Pascoal Faria, October 2007 22
* Special types Type Ocl. Any Ocl. Void Ocl. Invalid Ocl. Message Ocl. Type Description Supertype for all types except for collection and tuple types. All classes in a UML model inherit all operations defined on Ocl. Any. The type Ocl. Void is a type that conforms to all other types. It has one single instance called null. Any property call applied on null results in Ocl. Invalid, except for the operation ocl. Is. Undefined(). A collection may have null’s. The type Ocl. Invalid is a type that conforms to all other types. It has one single instance called invalid. Any property call applied on invalid results in invalid, except for the operations ocl. Is. Undefined() and ocl. Is. Invalid(). Template type with one parameter T to be substituted by a concrete operation or signal type. Used in some postconditions that need to constrain the messages sent during the operation execution. Meta type. OCL – Object Constraint Language, João Pascoal Faria, October 2007 23
Operations defined in Ocl. Any Operation Description =(object 2 : Ocl. Any) : Boolean True if self is the same object as object 2. <>(object 2 : Ocl. Any) : Boolean True if self is a different object from object 2. Can only be used in a postcondition. True if self was created during the operation execution. Cast (type conversion) operation. Useful for downcast. ocl. Is. New() : Boolean ocl. As. Type(t : Ocl. Type) : Ocl. Type ocl. Is. Type. Of(t: Ocl. Type) : Boolean ocl. Is. Kind. Of(t : Ocl. Type) : Boolean ocl. Is. In. State(s : Ocl. State) : Boolean True if self is of type t or a subtype of t. True if self is in state s. ocl. Is. Undefined() : Boolean True if self is equal to null or invalid. ocl. Is. Invalid() : Boolean True if self is equal to invalid. all. Instances() : Set(T) Static operation that returns all instances of a classifier. OCL – Object Constraint Language, João Pascoal Faria, October 2007 24
* Properties defined in Ocl. Message Operation has. Returned() : Boolean is. Signal. Sent() : Boolean is. Operation. Call() : Boolean Description True if type of template parameter is an operation call, and the called operation has returned a value. Returns the result of the called operation, if type of template parameter is an operation call, and the called operation has returned a value. Returns true if the Ocl. Message represents the sending of a UML Signal. Returns true if the Ocl. Message represents the sending of a UML Operation call. parameter. Name The value of the message parameter. result() OCL – Object Constraint Language, João Pascoal Faria, October 2007 25
User defined model types n n Model types are classes, association classes, interfaces, etc. defined in the model Properties of a model type are • Attributes • Operations and methods - Only query operations and methods can be used in OCL expressions • Navigations that are derived from the associations • Enumeration literals defined (as attributes) in an enumeration type - Syntax: Enum. Type: : Enum. Literal, as in Gender: : Male OCL – Object Constraint Language, João Pascoal Faria, October 2007 26
Navigation n Association end names (rolenames) are used to access corresponding objects across an association • If the rolename is absent, it’s used the classname starting with a lowercase letter n In the context of an instance x of C 1 • x. r 2 is of type C 2 • x. r 3 is of type C 3 C 2 C 3 r 2 1 0. . 1 C 1 - But can also be used as Set(C 3), as in r 2 ->not. Empty() implies … • x. r 4 is of type Set(C 4) • x. r 5 is of type Ordered. Set(C 5) r 3 r 4 C 4 * OCL – Object Constraint Language, João Pascoal Faria, October 2007 {ordered} r 5 * C 5 27
* Navigation: qualified associations Hotel customer. Number 1. . * customer 0. . 1 Customer Value of qualifier attribute can be used to navigate h 1: Hotel 1 2 h 2: Hotel 1 h 1[1] = c 1 h 1[2] = c 2 n h 2[1] = c 2 n c 1. hotel = Set {h 1} n c 2. hotel = Set {h 1, h 2} n h 1. costumer = Set {c 1, c 2} n c 2: Customer n n c 1: Customer h 2. costumer = Set {c 2} OCL – Object Constraint Language, João Pascoal Faria, October 2007 28
* Navigation: association classes Person employee * j 11: Job * p 1: Person Company c 1: Company j 12: Job Class name starting with a lowercase letter is used to navigate to the association-class p 2: Person c 2: Company j 22: Job n p 1. company = Set {c 1, c 2} n p 1. job = Set {j 11, j 12} n c 2. employee = Set {p 1, p 2} n c 2. job = Set {j 12, j 22} n j 12. company = c 2 n j 12. employee = p 1 OCL – Object Constraint Language, João Pascoal Faria, October 2007 29
* Navigation: recursive association classes er 12: ER boss Person 0. . 1 employees * score=3 p 1: Person boss employees p 2: Person Employee. Rating score employees p 3: Person boss er 34: ER score=2 employees p 4: Person Role names are needed to disambiguate navigation! er 13: ER score=2 er 35: ER score=1 employees p 5: Person n p 3. boss = p 1 n p 3. employees = Set {p 4, p 5} n p 3. employee. Rating[boss] = Set {er 13} n p 3. employee. Rating[employees] = Set {er 34, er 35} n er 13. boss = p 1 n er 13. employees = p 3 OCL – Object Constraint Language, João Pascoal Faria, October 2007 30
Auxiliary variables and operations n let: defines a variable to be used in an expression • context Person inv: let income : Integer = self. job. salary->sum() in if is. Employed then income >= 100 else income < 100 endif n def: defines an auxiliary variable or operation in the context of a classifier • Such variables and operations are attributes and operations with stereotype «Ocl. Helper» of the classifier • context Person def: income : Integer = self. job. salary->sum() def: has. Title(t : String) : Boolean = self. job->exists(title = t) OCL – Object Constraint Language, João Pascoal Faria, October 2007 31
Defining invariants OCL – Object Constraint Language, João Pascoal Faria, October 2007 32
What is a (class) invariant? n An invariant is a constraint on the possible states of an instance of a class • An invariant is a condition that must be always true • More precisely, the condition must hold at method execution boundaries, but can be violated in the middle of method execution n Is specified with “inv” keyword in the context of a classifier (class, interface, etc. ) • More precisely, in the context of an instance of a class (self) OCL – Object Constraint Language, João Pascoal Faria, October 2007 33
Writing invariants n Equivalent forms: context Booking inv: number. Of. Guests > 0 Booking number. Of. Guests context Booking inv: self. number. Of. Guests > 0 context r : Booking inv: r. number. Of. Guests > 0 context Booking inv R 1: -- with a name number. Of. Guests > 0 OCL – Object Constraint Language, João Pascoal Faria, October 2007 34
Common types of invariants n Domain constraints • Constraints on the set of possible values of an attribute n Unique constraints • An attribute or set of attributes in a class that cannot take the same value or set of values for two distinct instances of the class n Constraints related to loops in associations n Time constraints n Constraints that define derived elements n Existence rules • Rules that state that certain objects/values should exist/be defined when other objects/values exist/are defined n Generic business rules OCL – Object Constraint Language, João Pascoal Faria, October 2007 35
Example: Class diagram Person name: String gender: Gender father date. Of. Birth: Date 0. . 1 date. Of. Death: Date = null marital. Status: Marital. Status = Single * «enumeration» Gender male female wife 0. . 1 husband «enumeration» Marital. Status single married divorced widowed dead mother 0. . 1 * Date < (d 2: Date): Boolean <>(d 2: Date): Boolean <=(d 2: Date): Boolean >=(d 2: Date): Boolean OCL – Object Constraint Language, João Pascoal Faria, October 2007 36
Example: Invariants (1/2) context Person -- The father must be a male inv R 1: father->not. Empty() implies father. gender = Gender: : male -- The mother must be a female inv R 2: mother->not. Empty() implies mother. gender = Gender: : female -- The husband must be a male inv R 3: husband->not. Empty() implies husband. gender = Gender: : male -- The wife must be a female inv R 4: wife->not. Empty() implies wife. gender = Gender: : female -- Death cannot occur before birth inv R 5: date. Of. Death<>null implies date. Of. Death >= date. Of. Birth -- Parents must be born before their children inv R 6: mother->not. Empty() implies date. Of. Birth > mother. date. Of. Birth inv R 7: father->not. Empty() implies date. Of. Birth > father. date. Of. Birth OCL – Object Constraint Language, João Pascoal Faria, October 2007 37
Example: Invariants (2/2) -- There cannot exist two persons with the same name and date of birth inv R 8: not Person. all. Instances->exists(p 1, p 2 | p 1 <> p 2 and p 1. name = p 2. name and p 1. date. Of. Birth = p 2. date. Of. Birth) -- Wife and husband are defined only when marital status is married inv R 9: wife->not. Empty() = (gender = male and marital. Status = married) inv R 10: husband->not. Empty() = (gender = female and marital. Status = married) -- If the date of death is defined, the marital status is “dead” inv R 11: (date. Of. Death <> null) = (marital. Status = dead) OCL – Object Constraint Language, João Pascoal Faria, October 2007 38
Exercise: Formalize constraints {ordered} Invoice. Item Invoice number date 1 {candidate key: (number)} * number product quantity value {candidate key: (invoice, number)} OCL – Object Constraint Language, João Pascoal Faria, October 2007 39
Exercise: Formalize constraints Person members 1. . * {subset} 1 director * * Committee context Committee inv: members->includes(director) OCL – Object Constraint Language, João Pascoal Faria, October 2007 40
Exercise: Formalize constraints 0. . 1 Account Person {xor} 0. . 1 Company OCL – Object Constraint Language, João Pascoal Faria, October 2007 41
Exercise: Formalize constraints employees Person * boss 0. . 1 * subordinate employer 1 Company From same company Cannot be his/her own boss, directly or indirectly (acyclic) OCL – Object Constraint Language, João Pascoal Faria, October 2007 42
Defining pre and post conditions OCL – Object Constraint Language, João Pascoal Faria, October 2007 43
Pre-conditions and post-conditions n n In class diagrams we only indicate the syntax and signature of operations; their semantics can be specified through pre and post -conditions in OCL A pre-condition is a condition on the arguments and initial object state that must hold for the operation call to be valid • Indicated in OCL with keyword "pre: " n A post-condition is a a condition on the arguments, return value, final object state, and initial object state that must hold in the end of the operation execution, assuming the pre-condition is satisfied • Indicated in OCL with keyword "post: " • It specifies the intended result and state change (what), and not the algorithm (how) • The initial state (value) of an object field is indicated with "@pre" (see next) • The returned value is indicated with the keyword "result" OCL – Object Constraint Language, João Pascoal Faria, October 2007 44
A simple exercise n context class Math: : sqrt(x: Real) : Real pre: x >= 0 post: x = result * result post: result >= 0 n Illustrates a situation where the implementation is very different from the specification OCL – Object Constraint Language, João Pascoal Faria, October 2007 45
Accessing old values in post-conditions n property@pre – old value of a property of the current object (at the beginning of the operation execution) • attribute@pre, rolename@pre, operation@pre(arguments) n n n In the absence of “@pre”, it’s used the new value The old/new value of a property of an object created/destroyed during the operation execution cannot be accessed The use of @pre is not limited to the properties of self Before: After: obj 1 a 1 = v 1 obj 1 a 1 = v 4 r 1 obj 2: a 2 = v 2 obj 2 a 2 = v 5 obj 3 a 2 = v 3 r 1 obj 3 a 2 = v 6 • obj 1. r 1@pre = obj 2 • obj 1. r 1 = obj 3 • obj 1. a 1@pre = v 1 • obj 1. r 1@pre. a 2@pre = v 2 • obj 1. r 1. a 2@pre = v 3 • obj 1. a 1 = v 4 • obj 1. r 1@pre. a 2 = v 5 • obj 1. r 1. a 2 = v 6 OCL – Object Constraint Language, João Pascoal Faria, October 2007 46
Example: Class diagram Person name: String gender: Gender date. Of. Birth: Date date. Of. Death: Date = null marital. Status: Marital. Status = Single birth(name : String, gender : Gender, date: Date, mother: Person, father: Person) : Person father mother marriage(p: Person) 0. . 1 death(date: Date) 0. . 1 divorce() wife 0. . 1 * 0. . 1 husband * OCL – Object Constraint Language, João Pascoal Faria, October 2007 47
Example: Statemachine diagram Person life cycle birth divorced divorce single marriage married widowed death of wife or husband death dead OCL – Object Constraint Language, João Pascoal Faria, October 2007 48
Example: pre/post conditions (1/4) context Person: : birth(name: String, gender: Gender, date: Date, mother: Person, father: Peron) : Person -- pre-conditions that check arguments to prevent breaking invariants pre: mother<>null (? ) implies mother. gender = Gender: : female pre: father<>null (? ) implies father. gender = Gender: : male pre: mother<>null (? ) implies mother. date. Of. Birth < date pre: father<>null (? ) implies father. date. Of. Birth < date pre: not Person. all. Instances->exists(p | p. name = name and p. date. Of. Birth = date) -- post-conditions to define the new object state post: result. ocl. Is. New() post: result. name = name and result. gender = gender and result. mother = mother and result. date. Of. Birth = date and result. father = father -- post-conditions related to the marital status (according to state diagram) post: result. marital. Status = single OCL – Object Constraint Language, João Pascoal Faria, October 2007 49
Example: pre/post conditions (2/4) context Person: : marriage(mate: Person) -- pre-condition on the marital status (dynamic constraint, state diagram) pre: (Set {divorced, single, widowed})->includes(marital. Status) pre: (Set {divorced, single, widowed})->includes(mate. marital. Status) -- pre-conditions that check arguments and initial state -- to prevent breaking invariants pre: mate. gender <> self. gender -- post-conditions to define the new object state (state diagram) post: self. marital. Status = married post: mate. marital. Status = married -- post-conditions to define the new links between the two objects post: mate = (if self. gender = male then self. wife else self. husband endif) post: self = (if mate. gender = male then mate. wife else mate. husband endif) OCL – Object Constraint Language, João Pascoal Faria, October 2007 50
Example: pre/post conditions (3/4) context Person: : divorce() -- pre-condition on the marital status (dynamic constraint, state diagram) pre: self. marital. Status = married -- post-conditions on the marital status (dynamic constraint, state diagram) post: self. marital. Status = divorced post: let mate=(if self. gender=male then wife@pre else husband@pre endif) in mate. marital. Status = divorced -- post-conditions to define the new object state (additional info) post: self. wife = null and self. husband = null post: let mate=(if self. gender=male then wife@pre else husband@pre endif) in mate. wife = null and mate. husband = null OCL – Object Constraint Language, João Pascoal Faria, October 2007 51
Example: pre/post conditions (4/4) context Person: : death(d: Date) -- pre-condition on the initial object state and arguments pre: self. marital. Status <> dead -- dynamic constraint pre: self. date. Of. Birth <= d -- post-conditions to define the new object state post: self. marital. Status = dead post: self. date. Of. Death = d post: self. marital. Status@pre = married implies (let mate = (if gender = male then wife@pre else husband@pre endif) in mate. marital. Status = widowed and mate. wife = null and mate. husband = null and self. wife = null and self. husband = null) OCL – Object Constraint Language, João Pascoal Faria, October 2007 52
* Pre/post-conditions and inheritance n A subclass cannot contradict the contract (invariants and pre/post conditions) defined by the superclass: • Invariants are inherited by subclasses (which may add other invariants) • Pre-conditions may be weakened but not strengthened in subclasses - Any operation call that was valid in the superclass should continue to be valid for the subclass • Post-conditions may be strengthened but not weakened in subclasses - Any operation effect that was promised in the superclass must continue to be guaranteed in subclasses OCL – Object Constraint Language, João Pascoal Faria, October 2007 53
* Pre/post-conditions and inheritance Figure center: Point Resize(factor: real) Circle radius: Real Resize(factor: real) pre: factor <> 0. 0 post: center = center@pre and radius = radius@pre * factor pre Figure: : Resize(…) pre Circle: : Resize(…) post Figure: : Resize(…) post Circle: : Resize(…) OCL – Object Constraint Language, João Pascoal Faria, October 2007 54
* Post-conditions that check messages sent (1/2) n n object^message(args): Boolean - checks if at least one instance of message (operation call or sending of a signal) was sent to object during the execution of this operation object^^message(args) : Sequence(Ocl. Message) - gives the sequence of instances of message sent to object during the execution of this operation Useful when the effect of the operation includes the sending of messages to other objects with unknown effects (e. g. , callbacks) “? ” can be used for arguments of unknown or free value OCL – Object Constraint Language, João Pascoal Faria, October 2007 55
* Post-conditions that check messages sent (2/2) n Example in the Observer pattern: • Post-condition of operation has. Changed in class Subject checks if the operation update was called for each registered observer: context Subject: : has. Changed() post: observers->for. All(observer | observer^update()) • Assure that update is called once and only once for each observer: context Subject: : has. Changed() post: observers->for. All(o | (o^^update())->count() = 1) OCL – Object Constraint Language, João Pascoal Faria, October 2007 56
OCL Tools OCL – Object Constraint Language, João Pascoal Faria, October 2007 57
Tools n Special purpose OCL Tools • USE: A UML-based Specification Environment • Dresden OCL Toolkit - http: //st. inf. tu-dresden. de/oclportal/ - Reads UML models created with Poseidon for UML - Generates assertions in Java • Octopus: OCL Tool for Precise UML Specifications • Etc. n General purpse UML tools • Usually allow the definition of invariants and pre/postconditions in OCL, but provide no further significant support • Enterprise Architect, Microsoft Visio, Rational Rose, Poseidon for UML, Visual Paradigm, etc. OCL – Object Constraint Language, João Pascoal Faria, October 2007 58
USE: A UML-based Specification Environment n n Available at: http: //www. db. informatik. unibremen. de/projects/USE/ A tool for validating OCL specifications • The developer can create test cases and check if the specified constraints are satisfied for these test cases • USE checks the test cases with respect to invariants and pre- post-conditions n n There are special USE commands for creating and manipulating object diagrams that can be accumulated in command files There is some support for automated testing • USE has a snapshot sequence language and a snapshot generator • The snapshot sequence language enables the user to write high level implementations for the user defined operations, so that they can be tested OCL – Object Constraint Language, João Pascoal Faria, October 2007 59
Exercise n Develop a formal domain model for a library management system according to the following requirements: • The library lends books to library members (students, teachers, etc. ) for a limited period of time - Members are notified by e-mail when the loan expires • The library accepts requests for books that are currently on loan - The requests are served in a first-come first-served (FIFO) order - When a book with pending requests is returned to the library, the author of the oldest pending request is notified by e-mail to pickup the book; if this does not happen in a prescribed time, the request is cancelled - Book requests can be cancelled by their requesters at any time OCL – Object Constraint Language, João Pascoal Faria, October 2007 60
Individual assignment n n Develop a UML model, with a use case model and a formal domain model, for the course case study (class timetables and summaries) Produce a report (20 pages maximum) with • • Introduction Use case model (little detail) Domain model (more detailed, particularly invariants) Conclusions n The usage of an UML tool is mandatory n The usage of an OCL tool is optional, but is strongly encouraged n Estimated effort (in average): 10 hours n For any doubts, e-mail jpf@fe. up. pt n Send final report (PDF) and model files by e-mail to jpf@fe. up. pt until the 6 -November-2007 OCL – Object Constraint Language, João Pascoal Faria, October 2007 61
References and further reading n www. uml. org • Specifications and resources on UML, OCL, etc. n n The Object Constraint Language (Second Edition): Getting Your Models Ready for MDA, Jos Armer, Anneke Kleppe, Addison-Wesley, 2003 Business modeling with UML: Business Patterns at Work, Magnus Penker, Hans-Eriksson, Wiley, 2000 • “Chapter 5 – Business Rules” provides a good introduction to OCL and business rules OCL – Object Constraint Language, João Pascoal Faria, October 2007 62
Appendix A: A Hotel Management System example OCL – Object Constraint Language, João Pascoal Faria, October 2007 63
Diagrama de classes OCL – Object Constraint Language, João Pascoal Faria, October 2007 64
Restrições a domínios de atributos (1) n R 1) Em "Preço Serviço", o número de pessoas tem de ser maior que 0 context Preço_Serviço inv: número_de_pessoas > 0 n R 2) Em "Estadia", o número de pessoas tem de ser maior que 0 context Estadia inv: número_de_pessoas > 0 n R 3) Em "Reserva", o número de pessoas tem de ser maior que 0 context Reserva inv: número_de_pessoas > 0 n R 4) Em "Estadia_Quarto", o número de pessoas tem de ser maior que 0 context Estadia_Quarto inv: número_de_pessoas > 0 OCL – Object Constraint Language, João Pascoal Faria, October 2007 65
Restrições a domínios de atributos (2) n R 5) Em "Quarto", a capacidade tem de ser maior que 0 context Quarto inv: capacidade > 0 n R 6) Em "Preço_Serviço", o preço tem de ser maior que 0 context Preço_Serviço inv: preço > 0 OCL – Object Constraint Language, João Pascoal Faria, October 2007 66
Chaves simples (1) n R 7) Não podem existir dois clientes com o mesmo número, isto é, o número de cliente é chave context Cliente inv R 7: Cliente. all. Instances->is. Unique(número_de_cliente) n R 7') (Equivalente a anterior, porque só há 1 hotel) Um hotel não pode ter dois clientes com o mesmo número context Hotel inv R 7 b: clientes->is. Unique(número_de_cliente) Nota: Sempre que possível é de evitar usar classe. all. Instances, pois é fácil implementar numa base de dados mas é difícil implementar em objectos em memória (em memória prefere-se partir de um objecto raiz). OCL – Object Constraint Language, João Pascoal Faria, October 2007 67
Chaves simples (2) n R 8) (Chave alternativa) Não podem existir dois clientes com o mesmo número de bilhete de identidade ou passaporte (este atributo pode ser visto como uma combinação de tipo de documento + número de documento) context Cliente inv: Cliente. all. Instances->is. Unique( número_do_bilhete_de_identidade_ou_passaporte) n R 9) Não podem existir duas reservas com o mesmo número context Reserva inv: Reserva. all. Instances->is. Unique(número_da_reserva) n R 10) Não podem existir duas estadias com o mesmo número context Estadia inv: Estadia. all. Instances->is. Unique(número_da_estadia) OCL – Object Constraint Language, João Pascoal Faria, October 2007 68
Chaves simples (3) n R 11) Não podem existir dois quartos com o mesmo número context Quarto inv: Quarto. all. Instances->is. Unique(número) n R 12) Não podem existir dois empregados com o mesmo login context Empregado inv: Empregado. all. Instances->is. Unique(login) n R 13) Não podem existir duas facturas com o mesmo número context Factura inv: Factura. all. Instances->is. Unique(número) n R 14) Não podem existir dois serviços com o mesmo nome context Serviço inv: Serviço. all. Instances->is. Unique(nome) OCL – Object Constraint Language, João Pascoal Faria, October 2007 69
Chaves compostas n R 15) Em "Preço Serviço", não podem existir duas ocorrências para a mesma combinação de serviço, data de início e número de pessoas Tirando partido do conceito de tuplo (conjunto de componentes com nome e valor) introduzido na versão 2. 0 de OCL, pode-se escrever: variável/iterador (para desambiguar) context Preço_Serviço inv: Preço_Serviço. all. Instances->is. Unique(p : Preço_Serviço | separador entre Tuple{serviço : Serviço = p. serviço, iterador e expressão data_de_início: Date = p. data_de_início, número_de_pessoas : Integer = p. número_de_pessoas} ) Ou omitindo os tipos do iterador e dos componentes dos tuplos: context Preço_Serviço inv: Preço_Serviço. all. Instances->is. Unique(p | Tuple{serviço = p. serviço, data_de_início = p. data_de_início, número_de_pessoas = p. número_de_pessoas} ) OCL – Object Constraint Language, João Pascoal Faria, October 2007 70
Chaves em classes derivadas n R 16) Em "Preço Serviço", não podem existir duas ocorrências para a mesma data, número de pessoas e serviço (chave em classe derivada resultante de desdobrar "Preço Serviço" por datas) context Preço_Serviço inv: not Preço_Serviço. all. Instances->exists(p 1, p 2 | p 1 <> p 2 and p 1. serviço = p 2. serviço and Date. Interval. overlap(p 1. data_de_início, p 1. data_de_fim, p 2. data_de_início, p 2. data_de_fim, false) and p 1. número_de_pessoas = p 2. número_de_pessoas) Notas: 1) Esta restrição implica a restrição anterior (R 15) 2) Uma vez que o standard não inclui a definição do tipo Date, pressupõe -se definição apropriada dos tipos Date e Date. Interval (ver adiante) OCL – Object Constraint Language, João Pascoal Faria, October 2007 71
Restrições relacionadas com ciclos (1) n R 17) A reserva a que se refere uma estadia tem de ser do mesmo cliente que a estadia context Estadia inv: reserva->not. Empty() implies reserva. cliente = cliente Nota: "reserva" designa o objecto correspondente pela associação c/"Reserva", cuja multiplicidade é 0. . 1, pelo que é necessário fazer o teste n R 18) A reserva a que se refere um contacto tem de ser do mesmo cliente que o contacto context Contacto inv: reserva->not. Empty() implies reserva. cliente = cliente OCL – Object Constraint Language, João Pascoal Faria, October 2007 72
Restrições relacionadas com ciclos (2) n R 19) A estadia a que se refere um contacto tem de ser do mesmo cliente que o contacto. context Contacto inv: estadia->not. Empty() implies estadia. cliente = cliente n R 20) O contacto anterior a que se refere um contacto tem de ser do mesmo cliente que o contacto actual. context Contacto inv: contacto_anterior->not. Empty() implies contacto_anterior. cliente = cliente n Nota: ver mais em elementos derivados OCL – Object Constraint Language, João Pascoal Faria, October 2007 73
Restrições relacionadas com datas (1) n R 21) Numa reserva, a data de saída prevista tem de ser posterior à data de entrada prevista context Reserva inv: data_de_saída_prevista. is. After(data_de_entrada_prevista) n R 22) Numa reserva, a data de entrada prevista não pode ser anterior à data da reserva context Reserva inv: not data_da_reserva. is. Before(data_de_entrada_prevista) n R 23) Numa estadia, a data de saída tem de ser posterior à data de entrada context Estadia inv: data_de_saída. is. After(data_de_entrada) OCL – Object Constraint Language, João Pascoal Faria, October 2007 74
Restrições relacionadas com datas (2) n R 24) Numa estadia, a data de expiração do cartão de crédito tem de ser posterior à data de saída context Estadia inv R 24: data_de_expiração_do_cartão_de_crédito. is. After(data_de_saída) n R 25) Em "Estadia Quarto", a data da saída tem de ser posterior à data de entrada context Estadia_Quarto inv R 25: data_de_saída. is. After(data_de_entrada) n R 26) O intervalo de datas de uma ocorrência de "Estadia Quarto" (classeassociação), tem de estar contido no intervalo de datas da estadia correspondente context Estadia_Quarto inv R 26: Date. Interval. contains(estadia. data_de_entrada, estadia. data_de_saída, data_de_entrada, data_de_saída, true) OCL – Object Constraint Language, João Pascoal Faria, October 2007 75
Restrições relacionadas com datas (3) n R 27) Na relação entre contactos, a data-hora do contacto anterior tem de ser anterior à data-hora do contacto seguinte context Contacto inv R 27: contacto_anterior->not. Empty() implies contacto_anterior. data_hora. is. Before(data_hora) Nota: Pressupõe definição de tipo Date. Time com operações apropriadas OCL – Object Constraint Language, João Pascoal Faria, October 2007 76
Regras de existência n R 28) Têm de estar definidos preços para se aceitarem estadias ou reservas context e: Estadia inv R 28 a: e. data_de_entrada. get. Dates. Until(e. data_de_saída, true) ->for. All(d | e. serviço. preços ->exists( p | p. número_de_pessoas = e. número_de_pessoas and p. data_de_início. contains. Until(p. data_de_fim, d, true)) context r: Reserva inv 28 b: r. data_de_entrada_prevista. get. Dates. Until(r. data_de_saída_prevista, true) ->for. All(d | r. serviço. preços ->exists( p | p. número_de_pessoas = r. número_de_pessoas and p. data_de_início. contains. Until(p. data_de_fim, d, true) ) Notas: na realidade, seria mais correcto definir em Hotel atributos com número máximo de pessoas por estadia/reserva e gama de datas com preços definidos (data inicial e final), e obrigar depois a estarem definidos preços para todos os serviços, nº de pessoas e datas nas gamas definidas OCL – Object Constraint Language, João Pascoal Faria, October 2007 77
Consistência de preços n R 29) Aumentando o número de pessoas o preço (do grupo) não pode baixar context Preço_Serviço inv R 29: Preço_Serviço. all. Instances->for. All(p 1, p 2 | p 1. serviço = p 2. serviço and p 1. número_de_pessoas > p 2. número_de_pessoas and Date. Interval. overlap(p 1. data_de_início, p 1. data_de_fim, p 2. data_de_início, p 2. data_de_fim, true) implies p 1. preço >= p 2. preço) n R 30) Partindo um grupo o preço não pode baixar context Preço_Serviço inv R 30: Preço_Serviço. all. Instances->for. All(p 1, p 2, p 3 | p 1. serviço = p 2. serviço and p 1. serviço = p 3. serviço and Date. Interval. overlap(p 1. data_de_início, p 1. data_de_fim, p 2. data_de_início, p 2. data_de_fim, true) and Date. Interval. overlap(p 1. data_de_início, p 1. data_de_fim, p 3. data_de_início, p 3. data_de_fim, true) and Date. Interval. overlap(p 2. data_de_início, p 2. data_de_fim, p 3. data_de_início, p 3. data_de_fim, true) and p 1. número_de_pessoas = (p 2. número_de_pessoas + p 3. número_de_pessoas) implies p 1. preço <= p 2. preço + p 3. preço) OCL – Object Constraint Language, João Pascoal Faria, October 2007 78
Consistência de estados n R 31) Uma reserva no estado "efectivada" é uma reserva com uma estadia associada context Reserva inv R 31: (estado = 'efectivada') = estadia->not. Empty() n R 32) Assim que se ultrapassa a data de entrada prevista de uma reserva sem que o cliente compareça, uma reserva que não foi cancelada passa ao estado "cliente faltou" context Reserva inv R 32: (Date. cur. Date. is. After(data_de_entrada_prevista) and estadia->is. Empty() and estado <> 'anulada') = (estado = 'cliente faltou') OCL – Object Constraint Language, João Pascoal Faria, October 2007 79
Restrições relativas à ocupação do hotel (1) n R 33) O mesmo quarto não pode estar ocupado duas vezes na mesma data (isto é, não pode ter duas ocorrências de "Estadia Quarto" na mesma data) context Quarto inv R 33: estadia_Quarto->for. All( e 1, e 2 | e 1 <> e 2 implies Date. Interval. disjoint(e 1. data_de_entrada, e 1. data_de_saída, e 2. data_de_entrada, e 2. data_de_saída, true)) n R 34) O número de pessoas colocadas num quarto tem de estar compreendido entre 1 e a capacidade do quarto. context Estadia_Quarto inv R 34: número_de_pessoas >= 1 and número_de_pessoas <= quarto. capacidade OCL – Object Constraint Language, João Pascoal Faria, October 2007 80
Restrições relativas à ocupação do hotel (2) n R 35) Para qualquer data e estadia, a soma dos números de pessoas indicados em "Estadia Quarto" deve ser igual ao número de pessoas indicado em "Estadia" context e: Estadia inv R 35: e. data_de_entrada. get. Dates. Until(e. data_de_saída, true) ->for. All(d | e. número_de_pessoas = e. estadia_quarto ->select(q | q. data_de_entrada. contains. Until(q. data_de_saída, d, true)) ->collect(número_de_pessoas) ->sum() ) OCL – Object Constraint Language, João Pascoal Faria, October 2007 81
Restrições relativas à ocupação do hotel (3) n R 36) Deve ser possível satisfazer todas as reservas activas. context Reserva def: arranja. Quartos( grupos. Por. Colocar: Bag(Tuple(entrada: Date, saída: Date, n_pessoas: Integer)), grupos. Colocados : Set(Tuple(entrada: Date, saída: Date, quarto: Quarto)) ) : Boolean = ( grupos. Por. Colocar->not. Empty() implies let g = grupos. Por. Colocar->any(true) in Quarto. all. Instances->exists (q | grupos. Colocados->forall(gc | gc. quarto = q implies Date. Interval. disjoint(gc. entrada, gc. saída, g. entrada, g. saída, true)) and arranja. Quartos( if q. capacidade >= g. n_pessoas then grupos. Por. Colocar->excluding(g) else grupos. Por. Colocar->excluding(g) ->including(Tuple{entrada = g. entrada, saída = g. saída, n_pessoas = g. n_pessoas – q. capacidade}) endif, grupos. Colocados->including(Tuple{entrada = g. entrada, saída = g. saída, quarto = q}))) ) inv R 36: arranja. Quartos(Reserva. all. Instances->select(estado = 'activa')->collect( r | Tuple{entrada = r. data_de_entrada, saída = r. data_de_saída, n_pessoas = r. número_de_pessoas}), Estadia_Quarto. all. Instances->collect( eq | Tuple{entrada = eq. data_de_entrada, saída = eq. data_de_saída, quarto = eq. quarto})) OCL – Object Constraint Language, João Pascoal Faria, October 2007 82
Restrições relativas a elementos derivados n R 37) A capacidade do hotel é a soma das capacidades dos seus quartos (caso de dado calculado) Context Hotel inv R 37: capacidade = quartos->select(capacidade)->sum() n R 38) O cliente da factura é o cliente da estadia a que se refere a factura (caso de dado replicado) Context Factura inv R 38: cliente = estadia. cliente n R 39) O valor da factura é calculado em função dos preços tabelados Context Factura inv R 39: valor = estadia. serviço. preços ->select(p | p. número_de_pessoas = estadia. número_de_pessoas) ->collect(p | p. preço * Integer. max(0, 1+Date. difference( Date. min(estadia. data_de_fim, p. data_de_fim), Date. max(estadia. data_de_início, p. data_de_início))) ->sum() OCL – Object Constraint Language, João Pascoal Faria, October 2007 83
Restrições relativas a elementos derivados (OCL 2. 0) Na versão 2. 0 é possível escrever: n R 37') A capacidade do hotel é a soma das capacidades dos seus quartos Context Hotel: : capacidade : Integer derive: quartos->select(capacidade)->sum() n R 38) O cliente da factura é o cliente da estadia a que se refere a factura Context Factura: : cliente : Cliente derive: estadia. cliente n R 39) idem OCL – Object Constraint Language, João Pascoal Faria, October 2007 84
Definição dos tipos Date, Date. Time e Date. Interval (1) Date. Time cur. Date : Date to. Integer(): Integer is. After(d 2: Date) : Boolean is. Before(d 2: Date) : Boolean max(d 1: Date, d 2: Date) : Date min(d 1: Date, d 2: Date) : Date difference(d 1: Date, d 2: Date) : Integer is. After(d 2: Date. Time) : Boolean is. Before(d 2: Date. Time) : Boolean Date. Interval disjoint(left 1: Date, right 1: Date, left 2: Date, right 2: Date, open. Right: Boolean ) : Boolean overlap(left 1: Date, right 1: Date, left 2: Date, right 2: Date, open. Right: Boolean ) : Boolean contains(left 1: Date, right 1: Date, left 2: Date, right 2: Date, open. Right: Boolean ) : Boolean (. . . ) Apenas foram indicados métodos que não alteram estado, e que por isso podem ser usados em expressões OCL – Object Constraint Language, João Pascoal Faria, October 2007 85
Definição dos tipos Date, Date. Time e Date. Interval (2) n Definição de operações auxiliares em OCL (Ocl. Helper) context Date -- obtém conjunto de datas representadas por inteiros desde self até uma -- outra data (right), incluída ou excluída def: get. Dates. Until(right: Date, open. Right: Boolean) : Set(Integer) = if open. Right then Sequence{self. as. Integer(). . (right. as. Integer()-1)}->as. Set() else Sequence{self. as. Integer(). . right. as. Integer()}->as. Set() endif -- verifica se o intervalo que vai desta data (self) até outra data (right), -- incluída ou excluída, contém uma terceira data representada por inteiro def: contains. Until(right: Date, data: Integer, open. Right: Boolean ) : Boolean = data >= self. as. Integer() and data <= (if open. Right then right. as. Integer()-1 else right. as. Integer() endif) Nota: como não se pode dizer que são static, foram definidas em Date em vez de em Date. Interval OCL – Object Constraint Language, João Pascoal Faria, October 2007 86
n Definição de pré e pós-condições de reserva (1) Registo de reserva – 1ª versão, recebendo e devolvendo objectos context Reserva: : criar. Reserva ( cliente: Cliente, serviço: Serviço, número_de_pessoas: Integer, data_de_entrada_prevista: Date, data_de_saída_prevista: Date, número_do_cartão_de_crédito: Integer, titular_do_cartão_de_crédito: String, data_de_expiração_do_cartão_de_crédito: Date ): Reserva pre: número_de_pessoas > 0 -- R 3 and not data_de_entrada_prevista. is. Before(Date. cur. Date()) -- R 32 and data_de_saída_prevista. is. After(data_de_entrada_prevista) -- R 21 and data_de_expiração_do_cartão_de_crédito. is. After(data_de_saída_prevista) -- R 24 and Hotel. tem. Quartos(data_de_entrada_prevista, data_de_saída_prevista, número_de_pessoas) -- R 36 and serviço. tem. Preços(data_de_entrada_prevista, data_de_saída_prevista, número_de_pessoas) -- R 28 and Gestão. Cartões. cartão. Válido(número_do_cartão_de_crédito, titular_do_cartão_de_crédito, data_de_expiração_do_cartão_de_crédito) -- envolve acesso a sistema externo (continua) Exercício: definir em OCL as operações auxiliares tem. Quartos e tem. Preços (ver R 36 e R 28) OCL – Object Constraint Language, João Pascoal Faria, October 2007 87
Definição de pré e pós-condições de reserva (2) (continuação) post: result. ocl. Is. New() -- ou: Reserva. all. Instances = Reserva. all. Instances@pre->including(result) -- atributos com valores dados pelos argumentos da operação and result. número_de_pessoas = número_de_pessoas and result. data_de_entrada_prevista = data_de_entrada_prevista and result. data_de_saída_prevista = data_de_saída_prevista and result. número_do_cartão_de_crédito = número_do_cartão_de_crédito and result. titular_do_cartão_de_crédito = titular_do_cartão_de_crédito and result. data_de_expiração_do_cartão_de_crédito = data_de_expiração_do_cartão_de_crédito -- associações and result. serviço = serviço and result. cliente = cliente and result. estadia->is. Empty() and result. contacto_com_Cliente->is. Empty() Como dizer que não há mais alterações de estado além das referidas explicitamente? ! Pós-condição está escrita de forma construtiva! -- atributos calculados and result. data_da_reserva = Date. cur. Date() and result. estado = 'activa' and result. número_da_reserva = 1 + Reserva. all. Instances@pre-> iterate(r; maior. Num: Integer = 0 | maior. Num. max(r. número_da_reserva@pre)) OCL – Object Constraint Language, João Pascoal Faria, October 2007 88
Definição de pré e pós-condições de reserva (3) n Registo de reserva - 2ª versão, recebendo e devolvendo chaves de objectos context Reserva: : criar. Reserva ( número_de_cliente: Integer, nome_do_serviço: String, número_de_pessoas: Integer, data_de_entrada_prevista: Date, data_de_saída_prevista: Date, número_do_cartão_de_crédito: Integer, titular_do_cartão_de_crédito: String, data_de_expiração_do_cartão_de_crédito: Date ): Integer -- número_da_reserva pre: Cliente. all. Instances->exists(c| c. número_de_cliente = número_de_cliente) -- integridade referencial and Serviço. all. Instances->exists(s| s. nome = nome_do_serviço) -- integridade referencial and. . . (o resto como anteriormente) post: let cliente : Cliente = Cliente. all. Instances@pre-> select(c| c. número_de_cliente@pre = número_de_cliente)->any(true), serviço : Serviço = Serviço. all. Instances@pre-> select(s| s. nome@pre = nome_do_serviço)->any(true), novas_reservas : Set(Reserva) = Reserva. all. Instances - Reserva. all. Instances@pre in novas_reservas->size() = 1 and let reserva : Reserva = novas_reservas->any(true) in result = reserva. número_da_reserva and. . . (o resto como anteriormente, com "result" substituído por "reserva") OCL – Object Constraint Language, João Pascoal Faria, October 2007 89
Definição de pré e pós-condições de check-in (1) n Check-in com reserva prévia – versão em que quartos são atribuídos automaticamente context Estadia: : check. In. Com. Reserva(reserva: Reserva): Estadia pre: reserva. estado = 'activa' and reserva. data_de_entrada_prevista = Date. cur. Date() Exercício: escrever pré e pós-condição de check-out post: result. ocl. Is. New() and result. número_de_pessoas = reserva. número_de_pessoas@pre and result. data_de_entrada = reserva. data_de_entrada_prevista@pre and result. data_de_saída = reserva. data_de_saída_prevista@pre and result. número_do_cartão_de_crédito = reserva. número_do_cartão_de_crédito@pre and result. titular_do_cartão_de_crédito = reserva. titular_do_cartão_de_crédito@pre and result. data_de_expiração_do_cartão_de_crédito = reserva. data_de_expiração_do_cartão_de_crédito@pre and result. número_da_estadia = 1 + Estadia. all. Instances@pre-> iterate(r; maior. Num: Integer = 0 | maior. Num. max(r. número_da_estadia@pre)) and result. cliente = reserva. cliente@pre and result. serviço = reserva. serviço@pre and result. reserva = reserva and result. contacto_com_Cliente->is. Empty() and result. factura->is. Empty() (continua) OCL – Object Constraint Language, João Pascoal Faria, October 2007 90
Definição de pré e pós-condições de check-in (2) (continuação) -- actualização do estado da reserva and reserva. estadia = result and reserva. estado = 'efectivada' -- Condições a que tem de obedecer a atribuição automática de quartos (sem mudanças de quartos): -- selecção de quartos (já optimizada) and reserva. escolhas. Quartos. Possiveis@pre->includes(result. estadia_Quarto->collect(quarto) ) -- ver definição de escolhas. Quartos. Possiveis a seguir -- definição de datas de estadia em cada quarto (garantindo R 26) and result. estadia_Quarto->forall(eq | eq. data_de_entrada = result. data_de_entrada and eq. data_de_saída = result. data_de_saída) -- escolha de número de pessoas em cada quarto (garantindo R 34 e R 35) and result. estadia_Quarto->forall(eq | eq. número_de_pessoas >= 1 and eq. número_de_pessoas <= quarto. capacidade) and result. estadia_Quarto->collect(eq | eq. número_de_pessoas)->sum() = result. número_de_pessoas Neste caso, a pós-condição não fixa completamente o estado final (nomeadamente o conjunto de quartos escolhidos e o número de pessoas em cada quarto), apenas fixa as condições a obedecer na produção do estado final. OCL – Object Constraint Language, João Pascoal Faria, October 2007 91
Definição de operação auxiliar para escolher quartos (1) n context reserva: Reserva -- Obtém o conjunto de escolhas possíveis de quartos para uma reserva. -- Cada escolha é um conjunto com um ou mais quartos. -- As escolhas são efectuadas por forma a não inviabilizar a satisfação das outras reservas. -- São excluídas escolhas de quartos nitidamente inferiores em relação ao objectivo de maximizar -- a taxa de ocupação do hotel (aceitar mas estadias/reservas posteriores). def: escolhas. Quartos. Possíveis : Set(Quarto)) = let -- obtém o conjunto de quartos que não têm estadias em curso no período da reserva quartos. Livres : Set(Quarto) = Quarto. all. Instances->select(estadia_Quarto->forall(eq | Date. Interval. disjoint(eq. data_de_entrada, eq. data_de_saída, reserva. data_de_entrada, reserva. data_de_saída, true))), -- dado um conjunto de quartos livres, obtém (recursivamente) o conjunto dos seus subconjuntos -- não vazios, excluindo subconjuntos com quartos em excesso para satisfazer a reserva subconjuntos. Quartos(quartos : Set(Quarto)): Set(Quarto)) = if quartos->is. Empty() then Set{} else let este : Quarto = quartos->any(true), sem. Este : Set(Quarto)) = subconjuntos. Quartos(quartos->excluding(este)), com. Este : Set(Quarto)) = Set{este}}->union(sem. Este-> ->select(qq | qq->collect(capacidade)->sum() < reserva. número_de_pessoas) ->collect. Nested(qq | qq->including(este)) in sem. Este->union(com. Este) endif, só versão 2. 0; collect não serve pois não permite criar (continua) conjuntos de conjuntos (aplana tudo num só conjunto) OCL – Object Constraint Language, João Pascoal Faria, October 2007 92
Definição de operação auxiliar para escolher quartos (2) (continuação) -- verifica se uma escolha de quartos livres é válida, isto é, se o número de quartos é suficiente -- para satisfazer esta reserva e se não inviabiliza a satisfação das restantes reservas (usando -- a operação auxiliar arranja. Quartos definida a propósito da restrição R 36) escolha. Válida(quartos: Set(Quarto)) : Boolean = quartos->select(capacidade)->sum() >= reserva. número_de_pessoas and arranja. Quartos( Reserva. all. Instances->excluding(reserva)->select(estado = 'activa')->collect( r | Tuple{entrada = r. data_de_entrada, saída = r. data_de_saída, n_pessoas = r. número_de_pessoas}), Estadia_Quarto. all. Instances->collect( eq | Tuple{entrada = eq. data_de_entrada, saída = eq. data_de_saída, quarto = eq. quarto}) ->union(quartos->collect(q | Tuple{entrada = reserva. data_de_entrada, saída = reserva. data_de_saída, quarto =q. quarto}))), -- obtém as escolhas de quartos válidas para satisfazer a reserva, ainda sem optimizar -- (para já apenas garante que cada escolha de quartos não tem quartos em excesso) escolhas. Válidas : Set(Quarto)) = subconjuntos. Quartos(quartos. Livres)->select(s | escolha. Válida(s)), in escolhas. Válidos->select(s 1 | not escolhas. Válidas->exists(s 2 | Hotel. melhor. Escolha(s 2, s 1) )) -- ver definição de melhor. Escolha a seguir OCL – Object Constraint Language, João Pascoal Faria, October 2007 93
Definição de operação auxiliar para comparar escolhas (1) n context Hotel -- Compara duas escolhas de quartos, devolvendo true se a 1ª for nitidamente melhor que a 2ª -- no sentido de poder maximizar a taxa de ocupação do hotel (aceitar mais estadias/reservas) def: melhor. Escolha(escolha 1 : Set(Quarto), escolha 2 : Set(Quarto)) : Boolean = let -- verifica (recursivamente) se pode colocar um conjunto de grupos (cada grupo representado -- por um inteiro que dá a sua dimensão) num conjunto de quartos (cada quarto representado -- por um inteiro que dá a sua capacidade) pode. Colocar(dimensões. Grupos: Bag(Integer), capacidades. Quartos: Bag(Integer)): Boolean = dimensões. Grupos->not. Empty() implies let d = dimensões. Grupos->any(true) in capacidades. Quartos->exists (c | pode. Colocar(if c >= d then dimensões. Grupos->excluding(d) else dimensões. Grupos->excluding(d)->including(d-c) endif, capacidades. Quartos->excluding(c))), -- da reunião dos quartos de escolha 1 e escolha 2, obtém os que ficam livres ao optar por escolha 1 quartos. Livres 1 : Set(Quarto) = escolha 2 – escolha 1, -- da reunião dos quartos de escolha 1 e escolha 2, obtém os que ficam livres ao optar por escolha 2 quartos. Livres 2 : Set(Quarto) = escolha 1 – escolha 2 in escolha 1 ->size() <= escolha 2 ->size() -- optimização and escolha 1 ->collect(capacidade)->sum() <= escolha 2 ->collect(capacidade)->sum() -- optimização and pode. Colocar( quartos. Livres 2 ->collect(capacidade), quartos. Livres 1 ->collect(capacidade) ) and not pode. Colocar( quartos. Livres 1 ->collect(capacidade), quartos. Livres 2 ->collect(capacidade) ) -- (ver justificação a seguir) OCL – Object Constraint Language, João Pascoal Faria, October 2007 94
Definição de operação auxiliar para comparar escolhas (2) n Justificação: • Dadas duas escolhas de quartos capazes de satisfazer um pedido, suponhamos que as capacidades dos quartos que ficam livres (quartos não escolhidos) no 1º caso é A={a 1, a 2, . . . , an} e no 2º caso é B={b 1, b 2, . . . , bm} • Para saber qual dos conjuntos de quartos livres é melhor, temos de determinar duas coisas: (1) Qualquer que seja o conjunto de grupos, se cabe em A então também cabe em B? (2) Qualquer que seja o conjunto de grupos, se cabe em B então também cabe em A? • O pior caso para (1) (no sentido de caber em A mas poder não caber em B), é quando cada quarto em A fica completamente cheio com um grupo diferente dos outros quartos. Basta por isso testar esse caso. Para determinar (2) também basta testar o caso recíproco. • A primeira escolha é melhor que a 2ª se se verificar (2) mas não (1) • Obviamente, a comparação não é prejudicada se se retirarem dos dois conjuntos (A e B) os elementos que são comuns OCL – Object Constraint Language, João Pascoal Faria, October 2007 95
Defining the body of a query operation n Exemplo (OCL 2. 0): context Quarto: : obter. Quartos. Livres(entrada: Date, saída : Date, num. Pessoas : Integer): Set(Quarto) pre: saída. is. After(entrada) and num. Pessoas > 0 body: Quarto. all. Instances->select( q | q. capacidade>num. Pessoas and q. estadia_Quarto->exists(e | Date. Interval. disjoint(e. data_de_entrada, e. data_de_saída, entrada, saída, true) ) n n body: expressão equivale a post: result = expressão Pós-condição também se poderia indicar mas seria redundante OCL – Object Constraint Language, João Pascoal Faria, October 2007 96
Definição de valores iniciais de atributos n Semelhante a "derive", com "init" em vez de "derive" n Exemplos: • context Reserva: : data_da_reserva : Date init: Date. cur. Date • context Reserva: : estado : String init: 'activa' n Alternativa a indicar directamente o valor inicial no diagrama de classes com • atributo = valor. Inicial OCL – Object Constraint Language, João Pascoal Faria, October 2007 97
Appendix B: The Stack Example in USE OCL – Object Constraint Language, João Pascoal Faria, October 2007 98
Specification: “Stack. use” model Stack . . . class Stack -- parameterized classes not supported attributes elements: Sequence(String) capacity: Integer operations Stack(c: Integer) push(x: String) pop() top(): String end context Stack: : Stack(c : Integer) pre: c > 0 post: elements->is. Empty() post: capacity = c constraints context Stack inv: capacity > 0 inv: elements->size() <= capacity … context Stack: : push(x: String) pre: elements->size() < capacity post: elements = elements@pre->append(x) context Stack: : pop() pre: elements->not. Empty() post: elements@pre = elements>append(elements@pre->last) context Stack: : top() : String pre: elements->not. Empty() post: result = elements->last Open in the GUI in menu File -> Open specification … OCL – Object Constraint Language, João Pascoal Faria, October 2007 99
Testing: “Stack. cmd” !create s : Stack !set s. capacity : = 2 !set s. elements : = Sequence {'1'}>reject(true) -- truque pois não aceita Sequence{} … check -- invariants !openter s top() !opexit '1' !openter s push('1') !set s. elements : = Sequence{'1'} !opexit !openter s top() !opexit '1' !openter s push('2') !set s. elements : = Sequence{'1', '2'} !opexit !openter s pop() !set s. elements : = Sequence{'1'}->reject(true) !opexit Execute at console with “read Stack. cmd” Success messages are displayed in the console !openter s top() !opexit '2' … OCL – Object Constraint Language, João Pascoal Faria, October 2007 100
View diagrams OCL – Object Constraint Language, João Pascoal Faria, October 2007 101
Limitations of USE n Not supported: • New features of OCL 2. 0 • Definition of empty collections • Parameterized classes • Literal null (? ) OCL – Object Constraint Language, João Pascoal Faria, October 2007 102
c77b9e97919fd388050bdd2eb415c074.ppt