Está en la página 1de 23

Ingeniera de Software I

El lenguaje de especificacin OCL



2 cuatrimestre 2005






Limitaciones del diagrama de clases

Es sabido que dentro de la metodologa UML el diagrama de clases es una poderosa
herramienta de modelizacin de la naturaleza propia de la informacin. En este diagrama se
estructura la informacin especificando la naturaleza central de los tipos de objetos
referidos (clases) con sus referencias inter-clases (asociaciones, clases de asociacin junto
con sus correspondientes multiplicidades), adems de las relaciones jerrquicas entre clases
(herencia, especializacin, generalizacin). El objetivo del uso de esta herramienta es
establecer una abstraccin respecto a todos los casos particulares posibles, ofreciendo un
marco sintctico para definir la realidad del modelo, separando aquellos casos particulares
correctos (los contemplados dentro del diagrama de clases, que es una abstraccin de todos
ellos), de los que no. A esta separacin que provee el diagrama entre los casos particulares
correctos y los incorrectos, lo vamos a llamar el invariante inherente al diagrama, que
representa las restricciones propias que debe cumplir el modelo.
Sin embargo, estas restricciones provistas por el diagrama terminan siendo puramente
sintcticas. Pero seguramente existen otro tipo de restricciones que pueden presentarse, que
son condiciones que se deben aplicar a los objetos representados, y que se deben cumplir.
Estas restricciones son realmente semnticas (de significado), y se diferencian de las
inherentes al diagrama, que son puramente sintcticas. Para poder expresar estar
restricciones semnticas debemos poder expresar las condiciones propias de estas
restricciones semnticas, que no pueden ser representadas con el diagrama de clases. Para
esto es necesario poseer un lenguaje para poder escribir estas condiciones. Para ello, dentro
del contexto de UML y asociado al diagrama de clases, deberan estar anexadas las
condiciones escritas en un lenguaje que expresen todas aquellas restricciones semnticas y
otras caractersticas que no se pueden reflejar en el diagrama y que se pueden reflejar con
este mismo lenguaje.


OCL (Object Constraint Language)

El lenguaje de especificin OCL aparece en el documento Semntica de UML como
lenguaje propuesto para especificar las restricciones semnticas del diagrama de clases,
junto a otro tipo de definiciones. OCL se puede utilizar en cualquier contexto en que se use
el diagrama de clases al que est asociado (como por ejemplo, en el modelo conceptual o en
el diseo).
OCL es un lenguaje hbrido orientado a objetos-funcional, y es tipificado, porque usa el
concepto de tipos de datos. Estos tipos de datos se encuentran jerarquizados a travs de
relaciones de inclusin. Tambin existen varios tipos bsicos predefinidos (similares a los
de cualquier lenguaje), y unos pocos tipos paramtricos (o estructurados) predefinidos. Los
tipos no predefinidos van a estar asociados a las clases del diagrama de clases.
El componente central construdo por este lenguaje es la expresin, que se manipula a
travs de operaciones que garantizan la transparencia referencial y la falta de efectos
colaterales. Estas son caractersticas compartidas con los lenguajes funcionales, que son
declarativos. Toda expresin vlida para el lenguaje OCL debe tener asociado un tipo de
datos. Las expresiones se pueden mapear fcilmente al concepto de objetos, ya que cada
tipo bsico no predefinido se puede vincular a una clase del diagrama, y algunas de las
operaciones de un tipo bsico no predefinido se modelan como atributos y
mtodos/responsabilidades de la clase original. Las asociaciones entre clases tambin se
modelan en OCL usando los roles de ambas clases participantes en la asociacin, que deben
estar rotulados (en ambos extremos). El rol de una clase en una asociacin con una segunda
clase, expresa que ese rol es un pseudoatributo del tipo de dato vinculado a esa segunda
clase. Todos estos componentes asociados a las clases, tambin se ven reflejados en los
tipos de OCL.

Las expresiones del lenguaje OCL se estructuran hasta llegar a su punto ms alto, que es
el de formar parte de una definicin. En cada definicin de OCL se describe cada
restriccin semntica del diagrama de clases, junto a otras propiedades tambin descriptas
con expresiones. Cada definicin en OCL se aplica a lo que se llama un contexto, que
representa el destinatario del diagrama de clases sobre quien se aplica esa definicin. Entre
estos contextos se encuentran:

- Una clase (se aplica a todas expresiones-objetos cuyo tipo de datos asociado es el
vinculado a esta clase).
- Un mtodo/responsabilidad de una clase.
- Un atributo derivado de una clase.
- Un mtodo/responsabilidad derivado (tambin llamado query) de una clase.


Tipos de definiciones

1) Invariantes

context id
clase

inv: [[Descripcin del invariante]] exp
Bool


Representa una condicin (restriccin semntica) que deben cumplir todas las
expresiones-objetos pertenecientes al tipo de datos vinculados a la clase id
clase
. La
condicin a cumplirse se expresa en la expresin exp
Bool
que es de tipo Boolean (lgico). La
expresin booleana debe evaluar en verdadero si se aplica a expresiones-objetos
perteneciente al tipo de la clase en cuestin que son vlidos bajo este invariante. Para el
resto de las expresiones-objetos (que son invlidas segn este invariante), la expresin debe
evaluar en falso.
Estos invariantes pueden tener una descripcin optativa (que se escribe entre corchetes).

2) Invariantes de mtodo/responsabilidad

context id
clase
::id
metodo
(par
1
:T
1
, ,par
n
:T
n
)[:T
res
]
pre: [[Descripcin precondicin]] exp
Bool

post: [[Descripcin postcondicin]] exp
Bool


Define la aplicabilidad de un mtodo/responsabilidad (de nombre id
metodo
, existente
dentro de la clase id
clase
con parmetros formales par
1
a par
n
de tipo T
1
a T
n
, y con
imagen de tipo T
res
-slo en el caso que retorne una expresin-). La clusula pre refleja la
precondicin de este mtodo/responsabilidad, expresada en la primera expresin booleana
exp
Bool
, que deber retornar verdadero slo para aquellas expresiones-objetos para la cual
este mtodo sea aplicable. La clusula post refleja la postcondicin de este
mtodo/responsabilidad, expresada en la segunda expresin booleana exp
Bool
, que deber
retornar verdadero slo cuando el estado final de la expresin-objeto al que se le aplic este
mtodo/responsabilidad es consistente con el accionar del mismo.
No existiran problemas si el mtodo/responsabilidad retorna una expresin y no
modifica el estado interno de la expresin-objeto original, ya que la postcondicin slo
verificara el resultado que retorna. Pero si no retorna un valor (porque en realidad modifica
el estado interno de la expresin-objeto original), la naturaleza de la postcondicin es
distinta que la anterior, ya que existe un efecto colateral de por medio. En este ltimo caso
no se especifica cmo se actualiza el estado interno de la expresin-objeto original (ya que
esto no sera declarativo), sino la condicin en que debe quedar la expresin-objeto original
luego de aplicarle este mtodo/responsabilidad. Este invariante terminara reflejando en
forma declarativa su definicin en s misma.

3) Definicin de atributos derivados

context id
clase
::id
atributo
:T
derive: exp
T


Define un atributo derivado de nombre id
atributo
existente en la clase id
clase
, y que
retornar una expresin de tipo T. La expresin retornada por este atributo derivado, al
aplicarla sobre una expresin-objeto de la clase en cuestin, retornar la expresin exp
T
, que
tambin deber ser de tipo T.

4) Definicin de mtodos/responsabilidades derivados (queries):

context id
clase
::id
metodo
(par
1
:T
1
, ,par
n
:T
n
):T
[pre: [[Descripcin precondicin]] exp
Bool
]
body: exp
T


Define un mtodo/responsabilidad derivado Como es un mtodo/responsabilidad, el
contexto es idntico al de un mtodo/responsabilidad comn, con la diferencia que siempre
retornar una expresin (que deber ser de tipo T) y no provocar efectos colateriales. La
clusula pre optativa determina si es aplicable o no (segn el resultado de exp
Bool
) a cada
expresin-objeto de la clase. En forma anloga a los atributos derivados, en la clusula
body se especifica cul ser el valor retornado para cada expresin-objeto de la clase que
sea aplicable, a travs de la expresin exp
T
, que ser de tipo T.


Tipos de datos

1) Predefinidos

a) Bsicos

- Boolean (valores lgicos)
- Integer (valores enteros)
- Real (valores reales)
- String (valores de cadenas de caracteres)
- OCLAny (el tipo supremo jerrquico de todos los tipos no estructurados)
- OCLType (el tipo asociado a los metatipos -todo tipo puede verse como una
expresin de tipo OCLType)

b) Estructurados

- Collection(T)
- Set(T)
- Bag(T)
- OrderedSet(T)
- Sequence(T)
- Tuple{id
1
:T
1
,..., id
n
:T
n
}

El tipo Set(T) corresponde a los conjuntos de expresiones de tipo T, que no contienen
repeticiones y sus expresiones contenidas no poseen un orden posicional.
El tipo Bag(T) corresponde a los bags de expresiones de tipo T, que permiten contener
repeticiones y donde sus expresiones contenidas no poseen un orden posicional.
El tipo OrderedSet(T) corresponde a los conjuntos ordenados de expresiones de
tipo T, que no contienen repeticiones y sus expresiones contenidas poseen un orden
posicional.
El tipo Sequence(T) corresponde a las secuencias (listas) de expresiones de tipo T,
que permiten contener repeticiones y donde sus expresiones poseen un orden posicional.
El tipo Collection(T) corresponde a las colecciones de expresiones de tipo T. Es un
tipo que es abstracto y superior jerrquico de los cuatro anteriores.
El tipo Tuple{id
1
:T
1
,..., id
n
:T
n
} (con n>0) corresponde a las tuplas
(registros/records) con campos de nombre id
1
a id
n
, donde cada uno de ellos debe tener
asociada una expresin de tipo T
1
a T
n
respectivamente.

2) No predefinidos

Corresponden a cada clase y enumerado del diagrama de clases. Toda clase o enumerado
C se mapear al tipo asociado T
C
de OCL. Sin embargo, como abuso de notacin es normal
referirse al tipo como C (el mismo nombre de la clase), aunque no lo haremos en el resto de
este apunte. Aqu expresamos al tipo de la clase C como T
C
slo a los efectos de distinguir
la diferencia de conceptos entre clase y tipo.

En OCL cada atributo de una clase, al aplicarse a una expresin del tipo asociado a la
clase, retorna una expresin que tambin tendr un tipo asociado. Con esto, decimos, que
todo atributo tiene tambin un tipo asociado. Esto ya se dijo en la definicin de atributos
derivados, cuando se expres que stos retornan una expresin de un tipo resultante
especificado. Con esto, decimos que todo atributo atrib tiene asociado en OCL el tipo de
dato T
atrib
. Este tipo no es necesariamente nuevo (como en el caso de los provenientes de
clases o enumerados). Al no definir un tipo necesariamente nuevo, en este apunte diremos
que el tipo retornado es T.
Si utilizamos el diagrama de clases dentro del contexto del diseo, seguramente cada
atributo de cada clase tendr su tipo de datos asociado en forma explcita en la misma clase
del diagrama, y con esto se puede mapear al tipo correspondiente de OCL. El problema que
existe en el diagrama de clases del modelo conceptual es que en las clases conceptuales no
se especifican tipos de datos. Esto sugiere la idea de existencia de dominios -como
abstracciones respecto a los tipos- (los atributos de las clases conceptuales retornan un
objeto de un dominio, en lugar de una expresin-objeto de un tipo de datos). En este caso
hay que realizar un mapeo implcito de los dominios de los atributos a tipos bsicos de OCL
para poder expresar condiciones en OCL que se apliquen sobre los valores retornados por
estos atributos.


Constantes

1) Tipos predefinidos

a) Tipos bsicos

- De tipo Boolean: true, false
- De tipo Integer: constantes enteras (Ej: 5, 8, -76, ...)
- De tipo Real: constantes reales (Ej: -7.5, 5.9, 0.0, ...)
- De tipo String: constantes string entre caracteres y (Ej: Hola, ,
7*, ...)

b) Tipos estructurados

- De tipo Collection(T): no posee constantes porque es abstracto.
- De tipo Set(T): constantes de la forma Set {exp
1
, exp
2
, ..., exp
n
}, con n0,
y donde las expresiones exp
1
a exp
n
son todas de tipo T.
- De tipo Bag(T): constantes de la forma Bag {exp
1
, exp
2
, ..., exp
n
}, con
n0, y donde las expresiones exp
1
a exp
n
son todas de tipo T.
- De tipo OrderedSet(T): constantes de la forma OrderedSet {exp
1
, exp
2
,
..., exp
n
}, con n0, y donde las expresiones exp
1
a exp
n
son todas de tipo T.
- De tipo Sequence(T): constantes de la forma Sequence {exp
1
, exp
2
, ...,
exp
n
}, con n0, y donde las expresiones exp
1
a exp
n
son todas de tipo T.
- De tipo Tuple{id
1
:T
1
, ..., id
n
:T
n
}: constantes de la forma Tuple {id
1
:T
1
=
exp
1
,..., id
n
:T
n
= exp
n
}, donde las expresiones exp
1
a exp
n
son todas de tipo T
1

a T
n
respectivamente. En general, los tipos de los campos en las expresiones
de tipo tupla pueden omitirse.

2) No predefinidos

Slo los tipos asociados a los enumerados del diagrama de clases poseen constantes. Si c
fuera un valor dentro del enumerado E del diagrama de clases, entonces la expresin T
E
::c
es de tipo T
E
.

3) Constantes especiales

self: representa a cada expresin-objeto de una clase a las que se le quiere verificar
una propiedad o aplicar un atributo derivado o un mtodo/responsabilidad (derivado o no).
Es reconocida nicamente en las clusulas inv, pre, post, derive y body.
result: representa al valor retornado por un mtodo/responsabilidad comn que
retorna una expresin. Es reconocida nicamente en las clusulas post.

4) Parmetros

Los parmetros de mtodos/responsabilidades (comunes o derivados) se pueden utilizar
en aquellas clusulas pre, post, y body de aquellas definiciones donde aparecieron en la
clusula context.


Operaciones centrales sobre tipos no predefinidos

1) Atributos (comunes o derivados)

Si atrib es un atributo de la clase C que retorna una expresin de tipo T, y x es
una expresin de tipo T
C
, entonces x.atrib es una expresin de tipo T, que retorna
el valor del atributo atrib asociado a la expresin x. Se considera dentro de las
posibilidades, que un atributo pueda retornar una expresin de un tipo estructurado
(como por ejemplo, un conjunto).

2) Pseudoatributos de multiplicidad 1 (simple)

Si psatrib es un pseudoatributo de la clase C que la asocia a la clase D, y x es una
expresin de tipo T
C
, entonces x.psatrib es una expresin de tipo T
D
. Retorna la
expresin del tipo T
D
que se asocia va el rol psatrib a la expresin x.

3) Pseudoatributos de multiplicidad 0..1, 0..*, 1..* (mltiple)

Si psatrib es un pseudoatributo de la clase C que la asocia a la clase D, y x es una
expresin de tipo T
C
, entonces x.psatrib es una expresin de tipo Set(T
D
).
Retorna las expresiones del tipo T
D
que se asocian va el rol psatrib a la
expresin x. Las retorna como un set (conjunto) porque no pueden existir elementos
repetidos, y no existe un orden de aparicin en la coleccin retornada.

4) Pseudoatributos de multiplicidad 0..1, 0..*, 1..* con label {ordered}

Si psatrib es un pseudoatributo de la clase C que la asocia a la clase D, y x es una
expresin de tipo T
C
, entonces x.psatrib es una expresin de tipo
OrderedSet(T
D
). Es similar al caso anterior, y retorna a las expresiones
resultantes como un orderedset (conjunto con orden posicional) porque no pueden
existir elementos repetidos, y existe un orden de aparicin en la coleccin retornada
(indicado por la etiqueta {ordered}).

5) Mtodos/responsabilidades (comunes o derivados) que retornan un valor

Si met es un mtodo/responsabilidad de la clase C que recibe n parmetros de tipo
T
1
a T
n
, y retorna una expresin de tipo T, y existen expresiones exp
1
a exp
n
que son
de tipo T
1
a T
n
respectivamente, y x es una expresin de tipo T
C
, entonces
x.met(exp
1
,...,exp
n
) es una expresin de tipo T. Retorna el resultado de la
aplicacin del mtodo/responsabilidad met a la expresin x, usando como
parmetros a las expresiones exp
1
a exp
n
.

6) Mtodos/responsabilidades de clase (slo para contados casos)

Si met es un mtodo/responsabilidad de clase de la clase C que recibe n parmetros
de tipo T
1
a T
n
, y retorna una expresin de tipo T, y existen expresiones exp
1
a exp
n

que son de tipo T
1
a T
n
respectivamente, entonces T
c
.met(exp
1
,...,exp
n
) es una
expresin de tipo T. Retorna el resultado de la aplicacin del
mtodo/responsabilidad met a la clase C, usando como parmetros a las
expresiones exp
1
a exp
n
.

Todas estas oparaciones se pueden componer sucesivamente utilizando esta notacin.

El significado de la operacin de aplicacin de atributo es obtener la expresin asociada
al atributo de una expresin dada.
Adems de existir expresiones de la forma x.atrib , tambin existen otras de la forma
x.atrib@pre (slo dentro de las clusulas post) que representan el valor retornado por
el atributo atrib aplicado a la expresin x en el momento de la evaluacin de la
precondicin (el mismo valor que retornara la expresin x.atrib dentro de la clusula
pre correspondiente). Esto ltimo tambin se puede utilizar para pseudoatributos de
multiplicidad 1.
El significado de la operacin de aplicacin de pseudoatributo es obtener la o las
expresiones-objeto asociadas a una expresin dada en funcin de la asociacin con la clase
de las expresiones-objeto obtenidas. Esto permite pasar de una clase a otra. A la
composicin de pseudoatributos se la suele llamar informalmente navegacin por el
diagrama de clases.
El significado de la operacin de aplicacin de mtodo/responsabilidad es obtener la
expresin-objeto asociada a la aplicacin de este mtodo/responsabilidad.


Operaciones asociadas a los tipos bsicos predefinidos

Algunas de estas operaciones binarias se escriben sintcticamente como funciones infijas
(que se escriben entre sus dos argumentos), o con la notacin postfija caracterstica de la
orientacin a objetos, que se aplica al primero de sus dos argumentos, y el segundo
argumento se pasa como su nico parmetro. Lo mismo ocurre con las operaciones unarias,
de las que algunas se escriben con la notacin prefija funcional, y otras con la notacin
postfija que se aplica a su nico argumento y no posee parmetros.

1) De tipo Boolean

(exp
1
: Boolean and exp
2
: Boolean): Boolean
(exp
1
: Boolean or exp
2
: Boolean): Boolean
not(exp: Boolean): Boolean
(exp
1
: Boolean xor exp
2
: Boolean): Boolean
(exp
1
: Boolean implies exp
2
: Boolean): Boolean

Representan la conjuncin (and), disyuncin (or), negacin (not), disyuncin
exclusiva (xor) e implicacin material (implies).

(if (exp: Boolean) then (exp
true
: T) else (exp
false
: T) endif): T

Representa el if funcin, infijo de tres argumentos.

(exp
1
: T = exp
2
: T): Boolean
(exp
1
: T <> exp
2
: T): Boolean
(exp
1
: T < exp
2
: T): Boolean
(exp
1
: T <= exp
2
: T): Boolean
(exp
1
: T > exp
2
: T): Boolean
(exp
1
: T >= exp
2
: T): Boolean

Representan los operadores relacionales. El tipo T no puede ser cualquiera, sino un tipo
que tenga definido estos operadores.

2) De tipo Integer

(exp
1
: Integer + exp
2
: Integer): Integer
(exp
1
: Integer - exp
2
: Integer): Integer
(exp
1
: Integer * exp
2
: Integer): Integer
(exp
1
: Integer / exp
2
: Integer): Integer
Integer.abs(): Integer
Integer.div(exp: Integer): Integer
Integer.mod(exp: Integer): Integer
Integer.min(exp: Integer): Integer
Integer.max(exp: Integer): Integer

Representan las operaciones de suma (+), resta (-), producto (*), cociente (/, div),
valor absoluto (abs), resto (mod), mnimo (min) y mximo (max).

3) De tipo Real

(exp
1
: Real + exp
2
: Real): Real
(exp
1
: Real - exp
2
: Real): Real
(exp
1
: Real * exp
2
: Real): Real
(exp
1
: Real / exp
2
: Real): Real
Real.floor(): Real
Real.round(exp: Integer): Real

Representan las operaciones de suma (+), resta (-), producto (*), cociente (/), parte
entera -o mayor nmero entero devuelto como nmero real que es menor o igual al nmero
real dado- (floor) y valor redondeado a una cantidad de decimales dada (round).

4) De tipo String

String.size(): Integer
String.concat(exp: String): String
String.substring(exp
1
, exp
2
: Integer): String
String.toUpper(): String
String.toLower(): String
String.toInteger(): Integer
String.toReal(): Real

Representan las operaciones de cantidad de caracteres -longitud- (size), concatenacin
de dos cadenas (concat), obtencin de una subcadena de una cadena dada desde una
determinada posicin tomando una cierta cantidad de caracteres a partir de all
(substring), la conversin a maysculas (toUpper), a minsculas (toLower), a
entero (toInteger) y a real (toReal).


Operaciones asociadas a los tipos de Coleccin

Las operaciones de coleccin se aplican siempre sobre una expresin de tipo Collection
(o de alguno de sus cuatro subtipos concretos), y pueden o no tener parmetros. La
expresin de tipo coleccin que es receptora de esta operacin se escribe antes de la
operacin. Entre la coleccin receptora y la operacin debe ir el smbolo -> (que
reemplazara en este caso al caracter . tradicional). El operador -> , como el . , tambin se
puede componer sucesivamente.
Como siempre, las aplicaciones de estas operaciones no provocan efectos colaterales.
Esta es la lista de operaciones existentes:

Collection(T)->size(): Integer

Retorna la cantidad de elementos que posee la coleccin.

Collection(T)->empty(): Boolean

Retorna si la coleccin est vaca (no contiene elementos).

Collection(T)->notEmpty(): Boolean

Retorna si la coleccin no est vaca (contiene algn elemento).

Collection(T)->includes(exp: T): Boolean

Retorna si la expresin pasada como parmetro pertenece a la coleccin. El tipo T debe
poseer la igualdad y la desigualdad.

Collection(T)->excludes(exp: T): Boolean

Retorna si la expresin pasada como parmetro no pertenece a la coleccin. El tipo T
debe poseer la igualdad y la desigualdad.

Collection(T)->includesAll(exp: Collection(T)): Boolean

Retorna si la expresin-coleccin pasada como parmetro est includa en la coleccin
original. El tipo T debe poseer la igualdad y la desigualdad.

Collection(T)->excludesAll(exp: Collection(T)): Boolean

Retorna si la expresin-coleccin pasada como parmetro es disjunta respecto a la
coleccin original. El tipo T debe poseer la igualdad y la desigualdad.

Collection(T)->sum(): Integer

Retorna si la suma de los elementos que componen la coleccin. El tipo T debe poseer la
operacin de suma.

Set(T)->including(exp: T): Set(T)
Bag(T)->including(exp: T): Bag(T)
OrderedSet(T)->including(exp: T): OrderedSet(T)
Sequence(T)->including(exp: T): Sequence(T)

Retorna una coleccin que es la misma que la original, con el agregado de un nuevo
elemento, indicado por la expresin dada. El tipo de la coleccin retornada es el mismo que
el de la original.

Set(T)->union(exp: Set(T)): Set(T)
Set(T)->union(exp: Bag(T)): Bag(T)
Bag(T)->union(exp: Set(T)): Bag(T)
Bag(T)->union(exp: Bag(T)): Bag(T)
OrderedSet(T)->union(exp: OrderedSet(T)): OrderedSet(T)
OrderedSet(T)->union(exp: Sequence(T)): Sequence(T)
Sequence(T)->union(exp: OrderedSet(T)): Sequence(T)
Sequence(T)->union(exp: Sequence(T)): Sequence(T)

Retorna la unin de dos colecciones. Se asume que si alguna de las dos es de un tipo que
admite repeticiones, entonces la coleccin retornada podr contener repeticiones.

Set(T)->intersection(exp: Set(T)): Set(T)
Set(T)->intersection(exp: Bag(T)): Set (T)
Bag(T)->intersection(exp: Set(T)): Set (T)
Bag(T)->intersection(exp: Bag(T)): Bag(T)
OrderedSet(T)->intersection(exp: OrderedSet(T)): OrderedSet(T)
OrderedSet(T)->intersection(exp: Sequence(T)): OrderedSet(T)
Sequence(T)->intersection(exp: OrderedSet(T)): OrderedSet(T)
Sequence(T)->intersection(exp: Sequence(T)): Sequence(T)

Retorna la interseccin de dos colecciones. Se asume que si alguna de las dos es de un
tipo que no admite repeticiones, entonces la coleccin retornada no podr contener
repeticiones.

Set(Collection(T))->flatten(): Set(T)
Bag(Collection(T))->flatten(): Bag(T)
OrderedSet(Collection(T))->flatten(): OrderedSet(T)
Sequence(Collection(T))->flatten():Sequence(T)

Retorna el aplanado de una coleccin de colecciones, eliminando un nivel de
colecciones. Dicho de otra forma, retorna la concatenacin de todos los elementos de la
coleccin de colecciones original (que son colecciones). El tipo mandatorio de la coleccin
resultante es el ms "externo".

Las siguientes operaciones son de orden superior, ya que como parmetro de estas
operaciones se especifican funciones implcitas representadas por una variable ligada
(bounded variable) y una expresin-cuerpo que admite apariciones libres de la variable
ligada especificada (y que hace referencia a ella misma).

Collection(T)->forAll(var | exp: Boolean): Boolean

Retorna si todos los elementos de la coleccin original cumplen con la condicin dada.
La condicin se expresa en el parmetro de esta operacin, usando una variable ligada (var)
que se instancia con cada elemento de la coleccin, y la condicin a testear sobre cada una
de ellos (expresin lgica exp). Esta expresin admite apariciones libres de la variable var.

Collection(T)->forAll(var
1
, var
2
| exp: Boolean): Boolean

Retorna lo mismo que la siguiente expresin (suponiendo que c es una expresin de tipo
Collection(T)):
c->forAll(var
1
| c->forAll(var
2
| exp))

Set(T)->select(var | exp: Boolean): Set(T)
Bag(T)->select(var | exp: Boolean): Bag(T)
OrderedSet(T)->select(var | exp: Boolean): OrderedSet(T)
Sequence(T)->select(var | exp: Boolean): Sequence(T)

Retorna a todos los elementos de la coleccin original que cumplen con la condicin
dada en el parmetro. La variable ligada se vincula a cada elemento de la condicin, y la
expresin lgica retorna si el elemento dado queda o no en la coleccin resultante. La
coleccin resultante ser del mismo tipo que la original.

Set(T)->reject(var | exp: Boolean): Set(T)
Bag(T)->reject(var | exp: Boolean): Bag(T)
OrderedSet(T)->reject(var | exp: Boolean): OrderedSet(T)
Sequence(T)->reject(var | exp: Boolean): Sequence(T)

Retorna a todos los elementos de la coleccin original que no cumplen con la condicin
dada en el parmetro.

Set(T
1
)->collect(var | exp: T
2
): Bag(T
2
)
Bag(T
1
)->collect(var | exp: T
2
): Bag(T
2
)
OrderedSet(T
1
)->collect(var | exp: T
2
): Sequence(T
2
)
Sequence(T
1
)->collect(var | exp: T
2
): Sequence(T
2
)

Retorna un mapeo de todos los elementos de la coleccin orginal a una coleccin
resultante de la misma cantidad de elementos, donde cada elemento de la coleccin
resultante es el mapeado de la misma posicin en la coleccin original (si posee orden
posicional). La funcin de mapeo se expresa con la variable ligada (que se sustituye por
cada elemento de la coleccin original) y la expresin-cuerpo que indica el valor a retornar
en la coleccin resultante para la expresin original dada. El tipo de la expresin-cuerpo
ser el mismo que el de los elementos de la coleccin resultante.
Como luego de la aplicacin de esta operacin se pueden generar elementos repetidos en la
coleccin resultante que provienen de elementos distintos de la coleccin original, se asume
que la coleccin resultante debe admitir repetidos (de ah que no se retornan conjuntos),
para lograr mantener la misma cantidad de elementos respecto a la cantidad de elementos
de la coleccin original.

Collection(T
1
)->isUnique(var | exp: T
2
): Boolean

Retorna si todos los elementos de la coleccin, al mapearse cada uno de ellos al mapeo
propuesto (anlogo a la operacin collect) da como resultado una coleccin con todos
valores distintos (dos a dos). El tipo T
2
debe poseer la igualdad y desigualdad.

Collection(T)->iterate(var
1
; var
2
: T
2
= exp
inicial
| exp: T
2
): T
2


Retorna la aplicacin sucesiva de la funcin binaria de variables ligadas (var
1
,var
2
) y
cuerpo exp, iterando por cada uno de los valores de la coleccin original -que son los
valores usados en la sustitucin de la variable var
1
- y donde cada resultado parcial -
indicado en la expresin exp- se usa como parmetro-acumulador del paso siguiente -en la
variable var
2
-. El valor resultado original ser dado en la expresin exp
inicial
. El tipo T
2
que
se escribe luego de la variable var
2
debe ser obligatorio.
Ms fcilmente, el resultado de esta operacin se ve reflejado por el siguiente
pseudoalgoritmo (donde la coleccin original est indicada por la variable c):

res := exp
inicial

paraCada i indice de c
res := ((var
1
,var
2
) exp) (c[i],res)
fin-paraCada
retornar res

la expresin de la parte derecha de la asignacin del rengln 3 significa la aplicacin de una
funcin de dos parmetros. Esta operacin es anloga a la funcin foldl del lenguaje
funcional Haskell.

Todos los mtodos de coleccin que reciben parmetros de la forma (var | exp) (como
por ejemplo select, reject o collect) pueden ser escritos con otra sintaxis, a saber:

Collection(T)->operacion(var | exp)
Collection(T)->operacion(var: T | exp)
Collection(T)->operacion(exp)

El segundo caso es anlogo al primero, con la diferencia de que se puede realizar un
typecast sobre el tipo de los elementos de la coleccin por un subtipo de ste (similar al uso
de la operacin OCLasType que se comentar despus). Los vnculos de variables
reconocidos en la expresin exp son los reconocidos por el contexto de la expresin general
ms la variable var.

En el tercer caso, la variable var no aparece, y no puede aparecer libre como
subexpresin de la expresin exp. En exp todos los mtodos/responsabilidades, atributos y
pseudoatributos aplicados a un receptor no especificado, son asumidos que se aplican en
primera instancia a cada elemento de la coleccin, y en segunda instancia, a self. Si
hubiera algn problema de ambigedad, no se puede elegir esta opcin de sintaxis, y se
debe optar por alguna de las dos primeras. Lo ms comn para este caso es que exp sea un
atributo o pseudoatributo y la operacin en cuestin sea collect.

Como caso aparte, en la operacin forAll con el iterador sobre pares de elementos de
la coleccin dada, la expresin booleana del cuerpo del mtodo puede contener apariciones
libres de estas dos variables ligadoras, y que se ligaran a stas.

Notacin de punto aplicada a colecciones:

Existe la notacin de aplicaciones de atributos y pseudoatributos a colecciones con la
notacin del punto (aplicados como si no fueran colecciones). La definicin es la siguiente:

Si c es una expresin de tipo Collection(T) y psatrib es un pseudoatributo (o atributo)
sobre el tipo T, se define lo siguiente:


c->collect(psatrib) (si psatrib no es PAM)
c.psatrib
c->collect(psatrib)->flatten() (si psatrib es PAM)


PAM es el resumido de pseudoatributo mltiple.


Operaciones asociadas a colecciones especficas

(exp
1
: Set(T) - exp
2
: Set(T)): Set(T)

Retorna la diferencia entre dos conjuntos.

Set(T)->symmetricDifference(exp: Set(T)): Set(T)

Retorna la diferencia simtrica entre dos conjuntos.

Bag(T)->count(exp: T): Integer
Sequence(T)->count(exp: T): Integer

{
Retorna la cantidad de apariciones de la expresin dada en la coleccin. El tipo T debe
tener definida la operacin de igualdad.

Bag(T)->asSet(): Set(T)
OrderedSet(T)->asSet(): Set(T)
Sequence(T)->asSet(): Set(T)

Retorna la conversin de la coleccin dada en un Set. En el Set resultante el orden
posicional y la cantidad de apariciones se pierden.

Set(T)->asBag(): Bag(T)
OrderedSet(T)->asBag(): Bag(T)
Sequence(T)->asBag(): Bag(T)

Retorna la conversin de la coleccin dada en un Bag. En el Bag resultante el orden
posicional se pierde, y la cantidad de apariciones resultantes de los elementos si la
coleccin original es un conjunto es 1 para todos.

Set(T)->asOrderedSet(): OrderedSet(T)
Bag(T)->asOrderedSet(): OrderedSet(T)
Sequence(T)->asOrderedSet(): OrderedSet(T)

Retorna la conversin de la coleccin dada en un OrderedSet. En el OrderedSet
resultante la cantidad de apariciones se pierden, y el orden posicional de los elementos si la
coleccin original no tiene orden se crea con el orden natural sobre el tipo T (el tipo T debe
tener definida la operacin menor o igual).

Set(T)->asSequence():Sequence(T)
Bag(T)->asSequence(): Sequencet(T)
OrderedSet(T)->asSequence(): Sequence(T)

Retorna la conversin de la coleccin dada en una Sequence. Sobre la Sequence
resultante se crea el orden posicional con el orden natural sobre el tipo T si la coleccin
original no era ordenada, y crea la cantidad de apariciones de los elementos en 1 si la
coleccin original era un conjunto.

OrderedSet(T)->first(): T
Sequence(T)->first(): T

Retorna el primer elemento de la coleccin con orden posicional (si es que existe).

OrderedSet(T)->last(): T
Sequence(T)->last(): T

Retorna el ltimo elemento de la coleccin con orden posicional (si es que existe).

OrderedSet(T)->at(exp: Integer): T
Sequence(T)->at(exp: Integer): T

Retorna el elemento de la posicin exp dada de la coleccin con orden posicional (si es
que existe).

Sequence(T)->append(exp: Sequence(T)): Sequence(T)

Retorna la concatenacin de la secuencia exp luego de la secuencia original.

Sequence(T)->prepend(exp: Sequence(T)): Sequence(T)

Retorna la concatenacin de la secuencia exp antes de la secuencia original.

Sequence(T)->subSequence(exp
1
, exp
2
: Integer): Sequence(T)

Retorna la subsecuencia de la secuencia original que comienza en la posicin exp
1
, y
posee exp
2
cantidad de elementos a partir de all.


Jerarqua de tipos

Los tipos de datos se encuentran jerarquizados a travs del concepto de inclusin. Los
tipos includos heredan todas las propiedades (atributos, peudoatributos y
mtodos/responsabilidades) de sus tipos superiores (los que lo incluyen). La relacin de
inclusin estricta este tipos se refleja con el siguiente operador:

T
1
< T
2
si y slo si T
1
es un subtipo estricto de T
2


Las reglas propias del operador < de inclusin de tipos son las siguientes:

- Si A es una clase y B es una subclase de A en el diagrama de clases, entonces T
B
< T
A

- T < OCLAny (para todo tipo T no estructurado)
- T
1
< T
2
Set(T
1
) < Set(T
2
)
- T
1
< T
2
Bag(T
1
) < Bag(T
2
)
- T
1
< T
2
OrderedSet(T
1
) < OrderedSet(T
2
)
- T
1
< T
2
Sequence(T
1
) < Sequence(T
2
)
- Set(T) < Collection(T)
- Bag(T) < Collection(T)
- OrderedSet(T) < Collection(T)
- Sequence(T) < Collection(T)
- Integer < Real
- T : OCLType
- T
1
< T
2
y T
2
< T
3
T
1
< T
3


Se aceptan mltiples jerarquas asociadas a una misma clase, al igual que la existencia de
herencia mltiple (ya que estas dos caractersticas son aceptadas en el diagrama de clases).


Operacin de tuplas

Las campos de una tupla se comportan como si fueran atributos. Estos campos se
utilizan sobre una tupla para proyectar sus valores. O sea que vale lo siguiente:

Si x es una expresin de tipo Tuple{id
1
:T
1
, ..., id
n
:T
n
}, entonces x.id
i
es una
expresin de tipo T
i
.


Operaciones de clase

Dada una clase C del diagrama de clases, se le puede aplicar la siguiente operacin de
clase:

T
C
.allInstances(): Set(T
C
)

Retorna el conjunto de todas las expresiones-objeto de la clase C.

Existen otras operaciones que se aplican a cualquier clase, relacionadas con
metainformacin. Estas se aplican en realidad sobre las expresiones-objeto del tipo de las
clases del modelo, que son las expresiones del tipo OCLType. Estas son las operaciones:

OCLType.name(): String

Retorna el nombre de la clase.

OCLType.attributes(): Set(String)

Retorna el conjunto de los nombres de todos los atributos de la clase.

OCLType.associationEnds(): Set(String)

Retorna el conjunto de los nombres de todos los pseudoatributos (roles) de la clase.

OCLType.operations(): Set(String)

Retorna el conjunto de los nombres de todas las operaciones
(mtodos/responsabilidades).

OCLType.supertypes(): Set(OCLType)

Retorna el conjunto de los tipos inmediatamente superiores a la clase.

OCLType.allSupertypes(): Set(OCLType)

Retorna el conjunto de los tipos superiores a la clase (los inmediatamente superiores y
sus antipos ancestros).


Expresiones LET

Existe otro tipo de expresiones, muy utilizada para no repetir o simplificar evaluaciones.
Son las expresiones LET, que son expresiones con la siguiente sintaxis:

let var: T = exp
1
in exp
2


La evaluacin de esta expresin let consta de la evaluacin de la expresin exp
2
,
reemplazando antes todas las apariciones libres de la variable var (que dentro de exp
2
es
usada como expresin) por la expresin exp
1
. El tipo de var (T) debe especificarse, y debe
coincidir con el tipo del la expresin exp
1
.

Dentro de la expresin exp
2
se reconocen como expresiones a las vinculaciones a
variables reconocidas en el contexto de la expresin let, y a esta nueva variable var (que
slo es local a la expresin let).


En relacin a la creacin de expresiones-objetos de una clase

La creacin de objetos de una clase es una operacin de naturaleza destructiva. Es por
eso que stas no se modelan con OCL, que es declarativo. Lo que s se puede hacer con
OCL es verificar o establecer caractersticas de los objetos en funcin de su creacin. Para
ello se puede utilizar la siguiente operacin:

OCLAny.OCLisNew(): Boolean

Este mtodo (que se puede utilizar nicamente en la clusula post de la especificacin
de un mtodo/resposabilidad), retorna si la expresin-objeto receptora del mensaje fue
recientemente creada (durante la ejecucin del mismo mtodo -que no es especificado en
OCL-).

Relacionado con esto, en OCL se permite especificar el valor que tendr un atributo o
pseudoatributo de un objeto inmediatamente despus del momento de su creacin. Esto se
hace con una nueva clusula init, donde se especifican los valores iniciales de atributos y
pseudoatributos de objetos recientemente creados. El contexto utilizado es un atributo o
pseudoatributo propio de una clase, caracterstico de todas las instancias de esa misma
clase. Esta es su sintaxis:

context id
clase
::id
atributo
:T
init: exp
T


Con esto se especificar que el valor inicial que tendr el atributo o pseudoatributo
id
atributo
(de tipo T) para objetos recientemente creados pertenecientes a la clase dada, ser la
expresin exp
T
(que tambin debe ser de tipo T). Como est permitido especificar valores
iniciales tambin para los pseudoatributos, se podrn retornar expresiones de un tipo
estructurado de alguna coleccin. Tambin se pueden especificar valores iniciales de algn
tipo de tupla.

Dentro de la expresin exp
T
se puede utilizar la expresin self (hacer una referencia al
objeto recientemente creado), siempre y cuando de l se obtengan valores de atributos o
pseudoatributos, para los cuales su valor inicial haya sido especificado en una clusula
init anterior.


Sobre el uso de las clases de asociacin del diagrama de clases

Sean A y B clases, y C una clase de asociacin entre A y B (vamos a llamar tambin T
A
,
T
B
y T
C
a los tipos asociados a las clases A, B y C respectivamente). Sean exp
A
, exp
B
y exp
C

expresiones de tipos T
A
, T
B
y T
C
respectivamente, y dado el siguiente diagrama:




Valen las siguientes expresiones (ya vistas desde el comienzo):

exp
A
.rol
2
retorna una expresin de tipo Set(T
B
).
exp
B
.rol
1
retorna una expresin de tipo T
A
.

Adems de este caso, dentro del contexto de dos clases que se encuentran asociadas (A y
B en este caso), se puede usar el nombre de la clase de asociacin como pseudoatributo de
los tipos de las dos clases asociadas por esa asociacin. Lo retornado en este ltimo caso
son aquel o aquellas instancias de la asociacin (como si fueran pares) que poseen el valor
de la expresin del tipo de la clase origen, pero vistas como expresiones-objeto
pertenecientes al tipo de la clase de asociacin (T
C
). La multiplicidad de este
pseudoatributo-clase de asociacin es la misma que la multiplicidad del rol destino de la
misma asociacin. O sea que tambin vale lo siguiente:

exp
A
.C retorna una expresin de tipo Set(T
C
).
exp
B
.C retorna una expresin de tipo T
C
.

Por otro lado, dentro del contexto de un tipo-clase de asociacin, para toda expresin-
objeto de ese tipo, se puede obtener con qu expresiones de los dos tipos asociados se
asocia (siempre ser de multiplicidad 1). Para esto se utiliza como pseudoatributo los
nombres de los roles de la relacin original. O sea que vale:

exp
C
.rol
1
retorna una expresin de tipo T
A
.
exp
C
.rol
2
retorna una expresin de tipo T
B
.

Existe un caso que vale la pena distinguirlo, que es cuando la asociacin se presenta
entre una clase A y s misma (no existira una clase B). Este sera el caso:




El problema ocurre con las referencias al pseudoatributo-clase de asociacin C dentro
del contexto de la clase A, ya que habra que hacer explcito el rol origen de las
expresiones-objeto del tipo de la clase A a las que se refiere. Esto se hace escribiendo entre
corchetes el rol dentro de la asociacin:

exp
A
.rol
2
retorna una expresin de tipo Set(T
A
).
exp
A
.rol
1
retorna una expresin de tipo T
A
.
exp
A
[rol
1
].C retorna una expresin de tipo Set(T
C
)(toma a exp
A
desde rol
1
).
exp
A
[rol
2
].C retorna una expresin de tipo T
C
(toma a exp
A
desde rol
2
).


Sobre el uso de la herencia

Como OCL es tipado y existe una jerarqua de tipos (basado en herencia mltiple, que es
la del diagrama de clases), entonces se aplican las reglas de covarianza y contravarianza
presente en los chequeos de tipos de los lenguajes de programacin orientados a objetos
(Eiffel, Java, Object Pascal, etc).

Al tener como una de las vetas principales a la orientacin a objetos, se aceptan las
reglas de herencia (todas los tipos heredan los atributos, mtodos y pseudoatributos de sus
supertipos). Tambin se aceptan las reglas de sobrecarga de mtodos en subtipos. Esto
ltimo no es definitorio de la orientacin a objetos, pero se usa en todos los conceptos
relacionados con la orientacin a objetos.

Existen varias operaciones aplicables a cualquier tipo de expresin muy relacionadas con
el concepto de herencia y con la idea de tratar a los tipos de datos como datos propiamente
dichos (ya se mencion antes de OCLType, que es el metatipo), como por ejemplo,
expresar expresiones lgicas de la forma el tipo de la expresin var45 es
Set(Integer). Esto se relaciona con la idea de que una expresin es de un tipo, pero
tambin es de todos los supertipos de se (por el polimorfismo de inclusin propio de la
herencia). Estas operaciones son:

OCLAny.OCLisKindOf(exp: OCLType): Boolean

Retorna si el tipo de la expresin receptora (de tipo OCLAny) es exp o subtipo de exp.

OCLAny.OCLisTypeOf(exp: OCLType): Boolean

Retorna si el tipo de la expresin receptora (de tipo OCLAny) es idntico a exp.

T
1
.OCLasType(T
2
: OCLType): T
2


Retorna la misma expresin recibida (de tipo T
1
), aunque se asume que el tipo de esta
expresin retornada es de tipo T
2
. Representa el typecast elegante de la orientacin a
objetos, donde debe ocurrir que T
2
< T
1
. El objetivo del uso de esta operacin es poder
aplicar algn atributo, pseudoatributo o mtodo/responsabilidad de un subtipo del tipo de la
expresin si se sabe con seguridad que tambin pertenece a ese subtipo.


Sobre la recursin y los valores indefinidos

En OCL se permite utilizar recursin en todos las definiciones que se necesiten.

Dependiendo de la semntica de los mtodos/responsabilidades, la aplicacin de stos a
expresiones pueden retornar valores indefinidos. Todos los mtodos/responsabilidades,
atributos y pseudoatributos se consideran estrictos, con lo que si uno de sus parmetros (o la
expresin-objeto receptora) es indefinida (<undefined>), su resultado tambin ser
indefinido. Existen muy pocos casos donde no existe estrictez, y est relacionado a
operaciones sobre los valores lgicos, a saber:

if true then r else <undefined> endif = r
if false then <undefined> else r endif = r
true or <undefined> = true
false and <undefined> = false
false implies <undefined> = true

Relacionado con este tema, se puede utilizar la siguiente operacin:

OCLAny.OCLisUndefined(): Boolean

Retorna si la expresin receptora (de tipo OCLAny) es indefinida. Se usa bsicamente
para la captura de errores.


Bibliografa

- UML 2.0 OCL Specification (documento de la OMG publicado en Internet en http://
www.omg.org/docs/ptc/03-10-14.pdf).

- Object Constraint Language Specification (documento de Internet ubicado en
http://umlcenter.visual-paradigm.com/umlresources/obje_11.pdf).

- Muchos otros documentos extrados de Internet.

También podría gustarte