Using the new type system in CTs
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.
prepare_type_subtree_copy(+TypeRef, +Parent, -NewTypeRef, -NewIDs, -Actions)
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.
new_ids(+IDs)
This predicate has to be a part of the id creation. It creates a new ID for each element in the list.
execute_action_list(+Actions)
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.
Example: Copy fields
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:
Example: Problem when using type parameters
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.
prepare_type_subtree_copy(+TypeRef, +Parent, +MapList, -NewTypeRef, -NewIDs, -Actions)
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.
Example: Copy fields with type parameters
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 …).


