[Skip Navigation] [CSUSB] / [CNS] / [Comp Sci Dept] / [R J Botting] / [Samples] / ocl
[Index] [Contents] [Source Text] [About] [Notation] [Copyright] [Comment/Contact] [Search ]
Tue Sep 18 15:26:25 PDT 2007


Opening Microsoft files (winzip, word, excel, powerpoint) on this page may require you to download a special viewer. Or you can download and save the files and use your preferred office applications to view and edit them.

Contents


    The Object Constraint Language

      Introduction

      The Object Constraint Language - the OCL is used to specify constraints on objects in the UML. It has the power (but not syntax) of the Lower order Predicate Calculus (LPC) plus simple set_theory. Parts of the syntax seem to have been influenced by Smalltalk.

      Disclaimer -- Opinions expressed here may be Out of Date

      This page documents my understanding of the syntax and some of the semantics of the OCL. This description is based on the 1997 version 1.1 and certain 1999 version 1.3 updates. The latest version is 2.0 (2006/05/01, 232 pages of PDF) and is under revision by the OMG (see below).

      See Also

      The Object Management Group (OMG) [ OCL in modeling_spec_catalog ] maintains the standard.

      The Wikipedia [ Object_Constraint_Language ] has a very short introduction to the OCL. The WikiWikiWeb [ wiki?ObjectConstraintLanguage ] has a short discussion and some links.

      IBM holds a useful page [ ocl.html ] about the OCL which includes links to a parser(Java in a .zip file) and a specification of the language in Adobe PDF format. More information can be found at [ index.htm ] the Klasse Objecten Home.

      Glossary

    1. UML::="Unified Modeling Language", [ uml.html ]
    2. XBNF::="BNF stretched to its limit", [ math.syntax.html ]
    3. LPC::="Lower Predicate Calculus", a standard logic, [ logic_10_PC_LPC.html ]
    4. OCL::="Object Constraint Language", [ ocl ] [ ocl.html ]
    5. set_theory::= See http://www.csci.csusb.edu/dick/maths/logic_30_Sets.html
    6. Smalltalk::=Object oriented language developed at Xerox PARC by Alan Kay and friends, [ smalltalk.html ]
    7. Smalltalk_methods::= See http://www.csci.csusb.edu/dick/samples/smalltalk.methods.html.
    8. string_theory::= See http://www.csci.csusb.edu/dick/maths/math_61_String_Theories.html,
    9. strings::= See http://www.csci.csusb.edu/dick/maths/math_62_Strings.html.

      Syntax

        Notation

        The following Syntax description uses the conventions of the XBNF extended BNF including:
      1. O(_)::=an optional (_).
      2. #(_)::=any number of (_) including none.
      3. N(_)::=one or more of (_).
      4. For op, term, L(op, term)::=term #(op term), -- Infix operator expression.
      5. List(_)::= L( "," , (_) ).

        Grammar

      6. expression::= logical_expression.
      7. logical_expression::= L( logical_operator, relational_expression ).
         		score > 88.33 and score <= 93.33
         		gender = #female or gender = #male
         		p implies q
         		left xor right
         		next->isEmpty or value <= next.value
         		self.grading and self.questions->size<10
         		p1 <> p2 implies p1.name <> p2.name
         		Student.allInstances->forAll( p1, p2 | p1 <> p2 implies p1.name <> p2.name )
      8. relational_expression::= additive_expression O( relational_operator additive_expression ).
         		score > 88.33
         		value <= next.value
         		self.questions->size<10
      9. additive_expression::= L( add_operator, multiplicative_expression ).
         		golgafrensham + 42
         		golgafrensham - 42
         		self.questions->size+1
      10. multiplicative_expression::= L( multiply_operator, unary_expression ).
         		2 * head
         		22 / 7
         		20*self.questions->size
      11. unary_expression::= #( unary_operator ) postfix_expression.
         		- prefect
         		not ford
        		not self.questions->isEmpty
      12. postfix_expression::= primary_expression #(navigation_operator feature_call ).
         		self.questions
         		employees->includes(#dent)
         		self.questions->size
         		self.employer->size
         		self.employer->includes(self)
         		self.employee->select (v | v.wages>10000 )->size
         		Student.allInstances->forAll( p1, p2 | p1 <> p2 implies p1.name <> p2.name )
      13. primary_expression::= literal_collection | literal | feature_call | "(" expression ")" | if_expression.
         		42
         		self
         		#dent
         		employer@pre
         		MyClass::myMethod(myArgument)
         		self.employee->exists (v | v = self )
         		Student.allInstances
      14. if_expression::= "if" expression "then" expression "else" expression "endif".
         		if name = 'beeblebrox' then body->count(head) = 2 endif

      15. feature_call_parameters::= "(" O( declarator ) ( actual_parameter_list) ")".
         		( 42, #dent, x, self, 'beeblebrox')
         		( v:people | v.height < 6 )
         		( p1, p2 | p1 <> p2 implies p1.name <> p2.name )
      16. literal::= string | number | "#" name.
         		'beeblebrox'
         		42
         		#dent
      17. enumeration_type::= "enum" "{" List("#" name ) "}".
         		enum{ #female, #male }
      18. simple_type_Specifier::= path_type_name | enumeration_type.
      19. literal_collection::= collection_kind "{" O(expression_list_or_range) "}".
        (Set):
         		Set { 1 , 2 , 5 , 88 }
         		Set { 'apple' , 'orange', 'strawberry' }

        (Sequence):
         		Sequence { 1, 3, 45, 2, 3 }
         		Sequence { 'ape', 'nut' }
         		Sequence{ 10..24 }

        (Bag):
         		Bag {1 , 3 , 4, 3, 5 }

      20. expression_list_or_range::= expression O( N( "," expression ) | ( ".." expression )).
         		12,13,15
         		12..15
      21. feature_call::= path_name O(time_expression) O(qualifiers) O(feature_call_parameters).
      22. qualifiers::= "[" actual_parameter_list "]".
      23. declarator::= List(name) O( ":" simple_type_Specifier ) "|".
      24. path_type_name::= type_name #( double_colon type_name).
      25. path_name::= ( type_name | name ) #( double_colon ( type_name | name ) ).
         		MyClass::myAttribute
      26. time_expression::= "@" name.
         		@pre
      27. actual_parameter_list::= List( expression ).
         		1+1, 2, 3

        Lexicon

      28. double_colon::= colon colon.
      29. colon::= ":".
      30. logical_operator::= "and" | "or" | "xor" | "implies".
      31. collection_kind::= "Set" | "Bag" | "Sequence" | "Collection".
      32. relational_operator::= "=" | ">" | "<" | ">=" | "<=" | "<>".
      33. add_operator::= "+" | "-".
      34. multiply_operator::= "*" | "/".
      35. unary_operator::= "-" | "not".
      36. navigation_operator::= "." | "->"

      37. number::= digit #digit.
      38. type_name::= upper #idchar.
      39. name::= lower #idchar.
      40. idchar::= letter | digit | "_".
      41. string::="'" #( normal_char | backslash escape_sequence ) "'".
      42. backslash::="\\".

      43. normal_char::=char ~ ("'" | backslash | newline ).
      44. newline::= Newline and carriage return characters shown as "\n""\r" in C and C++ .
      45. escape_sequence::= "n" | "t" | "b" | "r" | "f" | backslash | "'" | doublequote | ASCII_code_number. -- compare with C/C++/Java
      46. ASCII_code_number::=odigit O( odigit ) | ("0".."3") odigit odigit
      47. doublequote::="\"".
      48. digit::="0".."9".
      49. odigit::=octal_digit.
      50. octal_digit::="0".."7".
      51. letter::= upper | lower.
      52. upper::="a".."z".
      53. lower::="A".."Z".

      . . . . . . . . . ( end of section Syntax) <<Contents | End>>

      Notes

        Using the OCL

          Comments

          Comments in OCL are written after two dashes. Everything after the two dashes up to and including the end of line is comment. For example:
           		-- this is a comment

          Class Invariants

          The context is shown first and then the invariant:
           		context Student
           		inv: self.age >= 0

          Operation Contracts

          In text the context of the operation is listed and then the pre-, and post-, conditions.
           	context Typename::operationName(parameter1 : Type1, ... ): ReturnType
           	    pre : parameter1 > ...
           	    post: result = ...
          (In an early version the context was underlined and the word "context" not used).

          In a post condition use "@pre" to indicate the value before the operation and "result" is the value returned.

          Operation Bodies

          These can be specified like this
           	context Typename::operationName(parameter1 : Type1, ... ): ReturnType
           		pre: some precondition
           		body: expression representing the body of the operation

          Initial Values

          These can be specified like this for an attribute or association end:
           	context Typename::propertyName: Type
           		init: expression representing the initial value

          Derived Attributes

          These can be specified like this for an attribute or association end:
           	context Typename::propertyName: Type
           		derive: expression representing the initial value

        . . . . . . . . . ( end of section Using the OCL) <<Contents | End>>

        Special Symbols

      1. self::Object. self refers to an object of the class being constrained
         		self.numberOfEmployees
        In most cases, self can be left out, because the context is clear, as in the above examples.

      2. result::Object. result is used in a post-condition inside an operation specification, to indicate the object returned

        Local Variables

        Within a context the lexeme "Let" allows the definition of a shorthand "variable" name for an expression:
         	let variable : type = expression.

        OCL Types

        Each class in a model that uses the UML defines a new type. There are other predefined types:
      3. type::= pathname | predefined_type.
      4. predefined_type::= basic_type | "OclExpression" | "OclType" | "OclAny".
      5. basic_type::= "Integer" | "Real" | "String" | "Boolean".

        OCL Types have the following features:


        1. For T:OclType.
        2. T.allInstances::Set(T), set of all instances of a type T in model.
        3. T.name::String, the name of the type.
        4. T.attributes::Set(String), the set of names of attributes of T as defined in the model.
        5. T.associationEnds: Set(string), set of names of navigable roles in model.
        6. T.operations::Set(string),
        7. type.supertypes::Ste(OclType).

        Properties of objects of Any Type

      6. OclAny::=following
        Net

          For o, o1:object, T: Types, s:possible states of object o in model.
        1. o = o1::Boolean.
        2. o <> o1::Boolean.
        3. o.oclIsKindOf(T):: Boolean.
        4. o.oclIsTypeOf(T):: Boolean.
        5. o.oclAsType(T)::T, cast.
        6. o.oclInState(s)::Boolean, new with 1.3.

        (End of Net)

        Navigation

        Starting from a specific object (or a path_name), we can navigate an association on the class diagram to refer to other objects and their properties. To do so, we navigate the association by using the opposite association-end:
                  object.rolename
        [ primary_expression ]

        The value of this expression is the set of objects on the other side of the role name association. If the multiplicity of the association-end has a maximum of one ("0..1" or "1"), then the value of this expression is an object. If the multiplicity is "0..1" then the result is an empty set if there is no object, otherwise it is the unique objet.

        Navigation expression generate Collections of objects. By default, navigation will result in a Set. When the association on the Class Diagram is adorned with {ordered}, the navigation results in a Sequence. Collections, like Sets, Bags and Sequences, are predefined types in OCL. They have a large number of predefined operations on them.

         		collection->operation(arguments)

        Collections

      7. Collection(T)::=Set(T) | Sequence(T) | Bag(T). Collections can be Sets, Sequences, and Bags.

        An object can occur at most once in a Set but many times in a Bag. It occurs at a particular position in Sequence. See literal_collection in the grammar above.

        Given a typename T then T.allInstances is the Set of all objects of type T.

        Operations on Collections

        Collections have many useful properties. These are added to the OCL to give it the power of symbolic logic (LPC) and naive set theory.

        Properties of collections are accessed by using an arrow '->' followed by the name of the property. There are many of these. They seem to have been borrowed from Smalltalk [Smalltalk_methods].

        Many of the properties of collections result in collections. This means that they can be chained together:

         		self.employee->select (v | v.wages>10000 )->size
        See postfix_expression in the grammar above.

        The following is a list of some of the commonest ones.


          For c,c1:Collection(T), v:variable, T,T1,T2:Type, e:expression, b:BooleanExpression, o1:object.
          (casts):
        1. c->asSequence::Sequence(T),
        2. c->sortBy(...)::Sequence(T).
          (size):
        3. c->size::Integer.
          (isEmpty):
        4. c->isEmpty::Boolean.
        5. |- (axiom1): c->isEmpty = (c->size = 0).
          (count):
        6. c->count(o1):: Integer=count of occurrences of o1 in c.
        7. |- (axiom2): c->count(o1) = c->select(v | v=o1)->size.
          (sum):
        8. c->sum::T.


          (filters): select, reject, collect, etc



            (select): c->select( v : T | b(v) ):: Collection(T), generates a collection by taking only elements v in c for which e(v) is true.
          1. c->select( b ):: Collection(T). v->select( v | e(v) ):: Collection(T).
            (reject): c->reject( v : T | b(v) ):: Collection(T) = c->select(v:T | not(e(v))).
            (collect): c->collect( v : T | e(v) ):: Collection(T), generates a collection made up of e(v) as v goes thru collection c. c->collect( v | e(v) ):: Collection(T).
          2. c->collect( e ):: Collection(T).


          (quantifiers): forAll and exists. Compare with LPC

            (forAll):
          1. c->forAll( v : T | b ):: Boolean = for all v:c&T ( b ).
          2. c->forAll( v | b ):: Boolean.
          3. c->forAll( b ):: Boolean.
            (exists):
          4. c->exists( v : T | b ):: Boolean = for some v:c&T ( b ).
          5. c->exists( v | b ):: Boolean.
          6. c->exists( b ):: Boolean.


          (iterate): c->iterate( v : T1; a : T2 = e0 | e(v,a) )::collection(T). The variable v is the iterator, as in the definition of select, forAll, etc. v takes each value in the collection c in turn. The variable a is the accumulator. The a gets an initial value e0. The e(v,a) is an expression that is repeatedly assigned to a. For example
        9. |-c->sum = c->iterate(v, a=0 | a+v).
        10. |-c->size = c->iterate(v, a=0 | a+1).


          (sets): includes, excludes, union, intersection, including, and excluding. Compare with set_theory. Plus (new in 1.3) unique, excludes, excludesAll



            (includes):
          1. c->includes(o):: Boolean= true if and only if o in c.
            (union):
          2. c->union(c2):: Set(T) = c|c2.
            (intersection):
          3. c->intersection(c2):: Set(T)= c&c2.
            (including):
          4. c->including(o)::Set(T) = c | {o}.
            (excluding):
          5. c->excluding(o):: Set(T) = c ~ {o}.


          (sequences): append, prepend, at, etc etc. See my strings and string_theory.

            (append):
          1. s->append(o):: Sequence(T) = s ! o, put o after s.
            (prepend):
          2. s->prepend(o):: Sequence(T) = o ! s, put o at the front of s.
            (at):
          3. s->at(i ):: T = s[i], pick out the i'th item in s.


        Undefined expressions

        Whenever an OCL expression is being evaluated, there is a possibility that one or more of the queries in the expression are undefined. If this is the case, then the complete expression will be undefined.

        Two exceptions are the boolean operators and + or:


        1. True OR-ed with anything is True
        2. False AND-ed with anything is False

        Notice, that if-then-else-endif does not evaulate all its arguments and so can be used to avoid an undefined object. In later OCL versions

         		oclUndefined()
        will recognize an undefined object and return True otherwise it returns False.

        Shorthand notation for collect


          In general, when we apply a property to a Collection of Objects, then the OCL will automatically be interpret it as a collect over the members of the Collection with the specified property. So
           		self.employee->collect(birthdate)
          is normally written
           		self.employee.birthdate
          and it means all the employee's birthdates.

      . . . . . . . . . ( end of section Notes) <<Contents | End>>

    . . . . . . . . . ( end of section The Object Constraint Language) <<Contents | End>>

End