SDA SE Wiki

Software Engineering for Smart Data Analytics & Smart Data Analytics for Software Engineering

User Tools

Site Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
research:jtransformer:tutorial_old:cts [2013/11/19 11:15]
fabian.noth
research:jtransformer:tutorial_old:cts [2018/05/09 01:59] (current)
Line 1: Line 1:
 +~~NOTOC~~
 +
 +~~NOTOC~~
 +====== Conditional Tranformations (CTs) ======
 +
 +<​note>​
 +If you want to enable logging for the CTs (to see which facts were added or deleted) you can call the predicate: //​enable_ct_logging/​0//​.
 +</​note>​
 +
 +JTransformer automatically creates an internal representation of [[..:​api:​java:​prologast| the Abstract Syntax Tree (AST)]] of a Java program as a Prolog database consisting of [[..:​api:​java:​pefs:​2.9:​java_pef_overview|Program Element Facts (PEF)]]. This representation can be manipulated using conditional transformations:​
 +
 +-> [[#basic cts|Basic CTs]]\\
 +-> [[#​parametrized conditional transformations| Parametrized CTs]]\\
 +-> [[#run conditional transformations| Run  CTs]]\\
 +-> [[#run the encapsulate field sample|Example:​ Encapsulate field]]\\
 +-> [[#view transformation results]]\\
 +-> [[#save transformation results]]\\
 +-> [[#further reading]]
 +
 +
 +===== Basic CTs =====
 +
 +Conditional Transformations (CT) are named specifications of program transformations. They consist of a name, a precondition and a transformation. If the precondtion holds the transformation is executed.
 +
 +A CT is represented in JTransformer by the Prolog fact ct/3. Its first argument is the head of the CT, the second one is its condition and the third one is the transformation description. ​
 +
 +Below is a simple '​addField'​ CT. It creates the field '​newField'​ in the class '​MyClass'​ and sets the field'​s visibility to public. If you don't use the //​JT_Tutorial//​ project just replace '​MyClass'​ by the name of any Class in your project.
 +
 +<Code lang-prolog>​
 +ct( addField, ​                                          % HEAD
 +    (                                                   % CONDITION
 +      classT(Class,​ _, '​MyClass',​ _),                   % Get the ID belonging to class '​MyClass'​
 +      not(externT(Class)), ​                             % ... which is no external class
 +      not( fieldT(Field,​ Class, _, '​newField',​ _) ),    % Make sure, that no field with the
 +                                                        %   name '​newField'​ exists
 +      new_id(Field) ​                                    % Field is a yet unused ID
 +    ),
 +    (                                                                     % TRANSFORMATION:​
 +      add(fieldT(Field,​ Class, type(basic, int, 0), '​newField',​ null)), ​  % Add the field
 +      add(modifierT(Field,​ '​public'​)), ​                                   % Make it public
 +      add_to_class(Class,​ Field) ​              % Let the class know, that it has a new member
 +    )
 +).
 +</​Code>​
 +
 +To run a CT you can specify it in a Prolog file. See [[..:#run conditional transformations]].
 +
 +The **head** can be any Prolog [[..:​api:​prologapi#​argument types|atom]]. It can be followed by an [[..:#​parametrized conditional transformations|optional parameter list]] and can be used to invoke the CT and pass parameters to the invokation.
 +
 +The **precondition** describes structural requirements on the program to be transformed. It consists of [[..:​api:​java:​pefs:​2.9:​java_pef_overview|Program Element Facts (PEF)]] connected by the usual boolean operators written in Prolog syntax:
 +
 +  * 'a AND b' is written 'a, b'
 +  * 'a OR b' is written 'a; b'
 +  * NOT(a) is written '​not(a)'​
 +
 +Every non-negated PEF in the precondition is a check whether a corresponding program element exists in the internal representation of the program that we want to transform. In addition, the predicate '​new_id(Id)'​ is used to generate unique identifiers for new PEFs to be created in the transformation part. It binds the free variable Id to a new, unique identifier. In the example above, this is used to generate the identifier for the PEF representing '​newField'​.
 +
 +The **transformation** part can contain a conjunction of the following operations that transform the fact representation as their names suggest:
 +
 +  * add(PEF)
 +  * delete(PEF)
 +  * replace(oldPEF,​newPEF)
 +
 +There are also some useful commands, which you can use in a transformation,​ under [[..:​api:​java:​transformations:​transformationapi|Java Transformations]].
 +
 +===== Parametrized Conditional Transformations =====
 +
 +You can parametrize a CT head by appending comma-separated variables enclosed by parenthesis. The parameters can be used to pass values to a CT application and to link multiple CTs that are invoked together:
 +
 +<Code lang-prolog>​
 +ct( addField(FName,​CName), ​                               % HEAD with parameters
 +    (                                                     % CONDITION
 +      classT(Class,​ _, CName, _),                         % Get the ID belonging to selected class
 +      not( externT(Class) ),                              % ... which should not be external ​
 +      not( fieldT(Field,​ Class, _, FName, _) ),           % Make sure, that no field with the given name exists
 +      new_id(Field) ​                                      % Field is a yet unused ID
 +    ),
 +    (                                                                      % TRANSFORMATION:​
 +      add(fieldT(Field,​ Class, type(basic, int, 0), FName, null)), ​        % Add the field to the class
 +      add(modifierT(Field,​ '​public'​)), ​                                    % Make the field public
 +      add_to_class(Class,​ Field) ​                                          % Let the class know, that this field is a new member  ​
 +    )
 +).
 +
 +
 +ct( makeFieldPrivate(FName,​ CName), ​                                  % HEAD with parameters
 +    (                                                                 % CONDITION
 +       ​classT(Class,​ _, CName, _),                                    % Get the class ID...
 +       ​fieldT(Field,​ Class, _, FName, _),                             % ... and the field ID
 +       ​modifierT(Field,​ Modif), ​                                      % Get the modifier...
 +       ​(Modif = '​public'​ ; Modif = '​protected'​ ; Modif = '​package'​) ​  % ...and make sure it is public, protected or package
 +    ),
 +   (
 +    replace( modifierT(Field,​Modif),​ modifierT(Field,'​private'​) )     % replace the selected modifier with private
 +   )
 + ).
 +</​Code>​
 +
 +
 +===== Run Conditional Transformations =====
 +
 +Conditional Transformations can be specified in Prolog files (extension '​.pl'​).
 +
 +**To run a CT** make sure it had been consulted((See:​ [[..:​stepbystep#​working_with_prolog_files|Working with Prolog files]] if you don't know how to consult a Prolog file)) and use the '​apply_ct(CT_Name)'​ predicate in the Prolog Console View. For instance, you can apply the '​addField'​ CT by executing the query:
 +
 +<Code lang-prolog>​
 +?- apply_ct(addField).
 +</​Code>​
 +        
 +**To run several CTs in sequence**, consult them and use the predicate '​apply_ctlist([ctHead1,​...])'​. The example below invokes the two parametrized CTs defined above, passing the desired arguments: ​
 +
 +<Code lang-prolog>​
 +?- apply_ctlist( [ addField('​testField',​ '​MyClass'​), ​
 +                   ​makeFieldPrivate('​testField','​MyClass'​) ]).
 +</​Code>​  ​       ​
 +
 +In either case, the invoked CTs are applied to all matching facts. So if you type: "​apply_ct(addField('​field123',​ Class)).",​ the field '​field123'​ will be added to //all classes//.
 +
 +Running a CT doesn'​t overwrite your existing Java source code, it only modifies your internal factbase. See [[..:#view transformation results]]. ​
 +
 +Note that substitutions computed for free variables in a CT invocation are not displayed in the Prolog console. In most cases there would simply be too many of them. Since all results are computed at once, backtracking on a CT application (by typing ';'​) will produce no new results.
 +
 +===== Run the Encapsulate Field Sample =====
 +
 +Let's take a look at a very useful example: Encapsulating fields
 +
 +If not already done, create a JT-Tutorial Prolog Project and consult the load.pl from the pl folder to your current factbase. (See [[..:​stepbystep#​working_with_prolog_files|Getting started -> Working with prolog files]]). It includes an encapsulateField example (//​pl/​refactoring/​encapsulateField.pl//​).
 +
 +Encapsulate a field means:
 +  * make the field private
 +  * create getField and setField methods
 +  * replace read access by calling the getField method
 +  * replace write access by calling the setField method
 +
 +All these transformations are implemented in the //​encapsulateField.pl//​ file. Paste the following query into your Prolog console (dont forget to add the '​.'​ period and press return):
 +
 +<​Code>​encapsulateField_JT(Class,​Field,​Ftype,​GetterName,​SetterName).</​Code>​
 +
 +Note that the above invocation does not limit the scope of the CT (all arguments are free variables). So the query asks to execute the encapsulateField refactoring on each field in the whole project that fulfills the conditions for being encapsulated. Therefore, it takes a a few seconds for JT to apply this refactoring to a large project. When the transformation is completed, the Console answers with a simple '​Yes'​.
 +
 +If you want to perform this transformation only on some classes you can use the following query:
 +<​Code>​classT(ClassID,​ _, '​MyClass',​ _), encapsulateField_JT(ClassID,​Field,​Ftype,​GetterName,​SetterName).</​Code>​
 +
 +The advantage of using CTs to encapsulate fields are the logic variables. With Eclipse refactoring tools you can just encapsulate single fields (or just for one class). You are not able to encapsulate all fields in your whole project, all int fields in your project, all fields in your project that start with a certain string and so on. Something like this can easily be done with CTs.
 +
 +
 +===== View Transformation Results =====
 +
 +Running CTs does NOT overwrite the existing source code. Only the internal factbase is modified. You can inspect it before deciding whether to save its new state as source code. 
 + 
 +To inspect the results of the transformation you can use a Factbase Inspector (FBI). ​
 +[[..:​factbase_inspector#​...|Open an FBI]] for a class that you expect to have been modified by the transformation. The new FBI's contents should look like this: 
 +
 +{{:​research:​jtransformer:​fbi_changed.png|}}
 +
 +The "​Factbase Inspector Help" Icon, indicated by the red circle in the upper screenshot, shows you a description of all icons used to indicate the status of a node in a Factbase Inspector:
 +
 +{{:​research:​jtransformer:​fbi_help.png|}}
 +
 +By double-clicking any node in the FBI you can either ​
 +  * see its original source code in the editor or
 +  * see its reverse-engineered source code (if there is no orginal source code) or
 +  * open a "​compare view" showing the original and the transformed source code (if the node was modified by a CT).
 +
 +The double-click is actually just a context-sensitive shortcut for different actions of the FBI context menu. The [[..:​factbase_inspector#​context menu|context menu]] offers additional actions to further inspect the results of your transformation. Just give it a try.
 +
 +===== Save Transformation Results =====
 +
 +CTs only modify the internal factbase. Your source code is left unmodified. ​
 +
 +If you want to save your results to source code but keep your input project unchanged select "Save To Output Project" ​ from the JTransformer menu. 
 +
 +|{{:​research:​jtransformer:​fbi_save_factbase.png?​450|}}| ​
 +
 +Then the modified code will be written to a **copy** of your original project.
 +
 +If you like the result of the transformation and wish to commit it to your **original** project(s) you can select "Save Factbase -> to Associated Project(s)..."​ from the JTransformer menu (shown above). Doing so opens a wizard that displays the usual side-by-side comparison of original and transformed source code and then writes the modified code to your original project:
 +
 +|{{:​research:​jtransformer:​fbi_save_factbase2.png?​500|}}|
 +
 +
 +
 +===== Undoing Transformations =====
 +
 +If inspection of the factbase reveals some error in the perfomed CT its execution can be undone. There is currently no GUI for this. You have into type the following to your Prolog console:
 +<​Code>​rollback.</​Code>​
 +
 +See also: [[..:​api:​meta:​transactions:​transactionapi|Transaction API]].
 +
 +===== Further Reading =====
 +
 +A significantly extended version of Conditional Transformations is supported by the [[..:​..:​ctc:​start|Conditional Treansformation Core (CTC)]], which is currently an independent project and will soon become the logic engine for the language-independent successor of JTransformer,​ [[..:​api:​meta:​startransformer|StarTransformer]]. The CTC offers different composition operators that go beyond the simple sequential execution via '​apply_ctlist([ctHead1,​...])'​. They support passing of bindings for free variables from one CT to another one in the same sequence. For example it's possible to combine an "Add Field" and an "​Encapsulate Fields"​ CT in the way, that only the added fields are encapsulated.
  
research/jtransformer/tutorial_old/cts.txt · Last modified: 2018/05/09 01:59 (external edit)

SEWiki, © 2019