This chapter describes all major changes to Frank Fingers OCL compiler. This includes bugfixes too, if they caused changes of internal or external interfaces. It it some kind of update for [FF00], listing everything changed since.
Many changes occurred both in the reflection model facade and in the OCL library. This section groups these changes.
Both ReflectionFacade.navigateParameterized and OclAnyImpl.getFeature lacked polymorphism of operation parameters. This means, that a method is found only if actual parameter types match formal parameter types exactly. The correct behavior is, that actual parameter types may also be subtypes of formal parameter types. For a detailed description see [RW00] section 3.1.5.
The new implementation made ReflectionAdapter.getClassForType superfluous, so it was removed from the interface.
Previous versions of the OCL library provided a default functionality, if no name adapter had been set explicitly.
Now it is mandatory to set a name adapter. Otherwise a NullPointerException is thrown. The default functionality has been moved into a separate name adapter (SimpleNameAdapter) which is used in the reflection facade as well. The name adapter may also be set by the java property tudresden.ocl.lib.nameadapter.
ArgoNameAdapter has been generalized into PrefixNameAdapter, which takes an arbitrary name prefix (``my'' for Argo/UML) as a constructor parameter. Using this adapter with ``lnk'' and ``the'' should work for Together/J and Rational Rose.
The OCL support was enhanced by adding a simplified form of qualified associations to the reflection facade and the OCL library. ``Simplified'' means, that there may be only one qualifier attribute.
Qualified associations are represented in java with java.util.Map by default, but this may be changed by implementing ReflectionAdapter.isMap(Class).
The mapping between OCL types and java types now supports the collections API introduced in JDK version 1.2. The changes concern DefaultOclFactory.getOclRepresentationFor(Object) and DefaultReflectionAdapter.getClassForType.
A special handling of java.util.Vector supports code generated by Argo/UML. The static configuration variable Ocl.TAKE_VECTORS_AS_SET causes vectors to be mapped to sets, instead of sequences.
The new mapping is listed below.
Java (java.util) | take vectors as set | OCL |
List | - | Sequence |
Vector | false | Sequence |
true | Set | |
Set | - | Set |
Map | - | Set (qualified) |
Furthermore, arrays are now supported. They are mapped into sequences of the appropriate element type.
Some modifications occurred in the OCL library only.
Previous versions of the OCL library implemented undefined values as singletons for each type.
This was given up. Now undefined values carry the reason for their creation with them. When the undefined value is tried to be evaluated, this reason is added to the exception message.
This made Ocl.STRICT_CHECKING superfluous, so it was removed. Wherever this property was used, the library now produces an undefined value, parameterized with the message of the exception formerly thrown.
Undefined values were introduced at some other operations of OCL objects:
Previous versions handled a special null value for OCL strings. This null value behaved like an empty string for most cases (e.g. concatenation). However a null string and an empty string were not equal. This was removed. Now a null string does exactly behave like an empty string.
Previous versions returned an undefined OCL collection, if the java collection field was null. Now, null collections are treated exactly like empty collections.
This behavior is encapsulated into a new method getOclRepresentationForNull(Class) in OclFactory. This method is called in OclAnyImpl.getFeature.
Previous versions of the type checker missed support for classifier OclAny in class DefaultTypeFactory.
Method getClassifier in class TypeFactory has been removed and replaced by TypeFactory.get.
Meaning of code fragments created for @pre expressions (TRANSFER, PREPARATION, POST) has been changed. The new behavior is easier and more flexible for different code instrumentation tools. For a description of the new behavior see section .
For the old behavior compare to [FF00] section 7.1.2. Below, there is a detailed comparison on the example used there.
The OCL expression is
final OclReal tudOclOpPar0=Ocl.toOclReal(Ocl.getFor(tax));
final OclReal tudOclResult0=OclReal.UNDEFINED;
final OclInteger tudOclNode1=Ocl.toOclInteger(
tudOclNode0.getFeature("age"));
final OclInteger tudOclNode2=Ocl.toOclInteger(
tudOclNode0.getFeature("age"));
final OclBoolean tudOclNode3=tudOclNode1.isEqualTo(tudOclNode2);
this.tudOclNode2=tudOclNode2;
final OclAnyImpl tudOclNode0=Ocl.toOclAnyImpl(Ocl.getFor(this));
final OclReal tudOclOpPar0=Ocl.toOclReal(Ocl.getFor(tax));
final OclReal tudOclResult0=Ocl.toOclReal(Ocl.getFor(result));
final OclInteger tudOclNode1=Ocl.toOclInteger(
tudOclNode0.getFeature("age"));
final OclBoolean tudOclNode3=tudOclNode1.isEqualTo(tudOclNode2);
{
// TRANSFER FRAGMENT
public double getIncomeAfterTax(double tax)
{
getIncomeAfterTaxPRE(tax);
// USER CODE
getIncomeAfterTaxPOST(tax, result);
return result;
}
private void getIncomeAfterTaxPRE(double tax)
{
// PREPARATION FRAGMENT
}
private void getIncomeAfterTaxPOST(double tax, double result)
{
// POST FRAGMENT
}
}
{
public double getIncomeAfterTax(double tax)
{
// TRANSFER FRAGEMENT
{
// PREPARATION FRAGMENT
}
// USER CODE
{
// POST FRAGEMENT
}
return result;
}
}
The java code generator now optionally prepends the explicit package qualifier tudresden.ocl.lib. to OCL library classes. This makes an import statement superfluous, and therefore fulfills the corresponding requirement in section .