SDA SE WikiSoftware Engineering for Smart Data Analytics & Smart Data Analytics for Software Engineering
Using the old type-terms in CTs was very easy. If we wanted to copy a field, it was enough to copy the type-term from the source field to the target field.
Now, with the new type system, it's not that easy. A field has now a type-reference (a reference to a typeRefT, arrayTypeT or a parameterizedTypeT). So if we want to copy this field, we have to copy the complete subtree representing the type information. Copying fields with a type variable as type might be even more complicated, because of the visibility of the type variable.
This can be done with the following predicates.
This predicate has to be a part of the condition. It copies the type subtree with root TypeRef to a new subtree with root NewTypeRef, which has Parent as parent. NewIDs is a list containing all variables which need IDs, Actions is a list containing all the actions which have to be executed in the transformation part of the ct.
This predicate has to be a part of the id creation. It creates a new ID for each element in the list.
This predicate has to be a part of the transformation. It executes all the actions in the list. In our case these are all facts which belong to the subtree, representig the type information.
ct(copyField(SrcClass, SrcField, FType, FName, TargetClass, TargetField), (
fieldT(SrcField, SrcClass, FType, FName, Init),
not(fieldT(_, TargetClass, _, FName, _)),
prepare_type_subtree_copy(FType, TargetField, NewFType, NewIdList, ActionList),
% Identities of elements to be created:
new_id(TargetField),
new_ids(NewIdList)
),(
execute_action_list(ActionList),
add(fieldT(TargetField,TargetClass,NewFType,FName, Init)),
add_to_class(TargetClass,TargetField)
)).
This ct can copy fields from one class to another. By using the new predicates, all the type-subtrees are copied. With this ct it's not possible to update the type references. See the following example:
public class A<T> {
T t;
...
} | copy field t to → | public class B<U> {
...
} |
In this case we have a problem with the current CT. If we copy the field t with a type reference to the type parameter T to class B, the type parameter T is still a reference to class A and is not visible in class B. For this, there is another predicate where it is possible to replace multiple type references in a subtree.
This predicate does the same like the predicate from above. Additionally we have the possibility to replace type references with the MapList parameter. The Maplist is a pair of lists. Each element in the first list is replaced by the corresponding element in the second list.
ct(copyField(SrcClass, SrcField, FType, FName, TargetClass, TargetField, OldRefs, NewRefs), (
fieldT(SrcField, SrcClass, FType, FName, Init),
not(fieldT(_, TargetClass, _, FName, _)),
prepare_type_subtree_copy(FType, TargetField, NewFType, (OldRefs, NewRefs), NewIdList, ActionList),
% Identities of elements to be created:
new_id(TargetField),
new_ids(NewIdList)
),(
execute_action_list(ActionList),
add(fieldT(TargetField,TargetClass,NewFType,FName, Init)),
add_to_class(TargetClass,TargetField)
)).
Now we can call this CT and replace the reference to a type-parameter T with the reference to another type-parameter U.
classT(SrcClass, _, 'A', _), classT(TargetClass, _, 'B', _), typeParamT(OldRef, SrcClass, 'T', _), typeParamT(NewRef, TargetClass, 'U', _), apply_ct(copyField(SrcClass, SrcField, FType, FName, TargetClass, TargetField, [OldRef], [NewRef])).
This CT copies the field t from class A to class B and replaces the Type T with U. This is possible for all references (replaces int with double, double with Double, String with Object …).