Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package org.refactoringminer.astDiff.actions;
import com.github.gumtreediff.actions.EditScript;
import com.github.gumtreediff.actions.model.*;
import com.github.gumtreediff.matchers.Mapping;
import com.github.gumtreediff.matchers.MappingStore;
import com.github.gumtreediff.tree.FakeTree;
import com.github.gumtreediff.tree.Tree;
import com.github.gumtreediff.tree.TreeContext;
import com.github.gumtreediff.tree.TreeUtils;
import org.refactoringminer.astDiff.utils.TreeUtilFunctions;
import org.refactoringminer.astDiff.actions.model.MoveIn;
import org.refactoringminer.astDiff.actions.model.MoveOut;
import org.refactoringminer.astDiff.matchers.ExtendedMultiMappingStore;
import java.util.*;
/**
* An edit script generator based upon Chawathe algorithm supporting multi-mappings.
* @author Pourya Alikhani Fard [email protected]
*/
public class ChawatheScriptGenerator implements EditScriptGenerator {
private Tree origSrc;
private Tree cpySrc;
private Tree origDst;
private MappingStore origMappings;
private MappingStore cpyMappings;
private Set dstInOrder;
private Set srcInOrder;
private EditScript actions;
private Map origToCopy;
private Map copyToOrig;
private ExtendedMultiMappingStore multiMappingStore;
private Map childContextMap;
private Map parentContextMap;
@Override
public EditScript computeActions(ExtendedMultiMappingStore ms, Map parentContextMap, Map childContextMap) {
this.parentContextMap = parentContextMap;
this.childContextMap = childContextMap;
this.multiMappingStore = ms;
initWith(ms.getMonoMappingStore());
generate();
return actions;
}
public void initWith(MappingStore ms) {
this.origSrc = ms.src;
this.cpySrc = this.origSrc.deepCopy();
this.origDst = ms.dst;
this.origMappings = ms;
origToCopy = new HashMap<>();
copyToOrig = new HashMap<>();
Iterator cpyTreeIterator = TreeUtils.preOrderIterator(cpySrc);
for (Tree origTree: TreeUtils.preOrder(origSrc)) {
Tree cpyTree = cpyTreeIterator.next();
origToCopy.put(origTree, cpyTree);
copyToOrig.put(cpyTree, origTree);
}
cpyMappings = new MappingStore(ms.src,ms.dst);
for (Mapping m: origMappings)
cpyMappings.addMapping(origToCopy.get(m.first), m.second);
}
public EditScript generate() {
Tree srcFakeRoot = new FakeTree(cpySrc);
Tree dstFakeRoot = new FakeTree(origDst);
cpySrc.setParent(srcFakeRoot);
origDst.setParent(dstFakeRoot);
actions = new EditScript();
dstInOrder = new HashSet<>();
srcInOrder = new HashSet<>();
cpyMappings.addMapping(srcFakeRoot, dstFakeRoot);
List bfsDst = TreeUtils.breadthFirst(origDst);
for (Tree x: bfsDst) {
Tree w;
Tree y = x.getParent();
Tree z = cpyMappings.getSrcForDst(y);
if (!cpyMappings.isDstMapped(x)) {
if(!multiMappingStore.isDstMultiMapped(x)) {
int k = findPos(x);
// Insertion case : insert new node.
w = new FakeTree();
// In order to use the real nodes from the second tree, we
// furnish x instead of w
Action ins = new Insert(x, copyToOrig.get(z), k);
actions.add(ins);
copyToOrig.put(w, x);
cpyMappings.addMapping(w, x);
if(z != null)
z.insertChild(w, k);
}
else
{
continue;
}
} else {
w = cpyMappings.getSrcForDst(x);
if (w == null)
{
if (origMappings.getSrcForDst(x).equals(TreeUtilFunctions.getFakeTreeInstance()))
{
}
else {
TreeUtilFunctions.getFinalRoot(origMappings.getSrcForDst(x));
actions.add(new MoveIn(origMappings.getSrcForDst(x), x, findNameByTree(parentContextMap, origMappings.getSrcForDst(x)), +1));
}
}
else if (!x.equals(origDst)) { // TODO => x != origDst // Case of the root
Tree v = w.getParent();
if (!w.getLabel().equals(x.getLabel())) {
actions.add(new Update(copyToOrig.get(w), x.getLabel()));
w.setLabel(x.getLabel());
}
if (z != null) {
if (!z.equals(v)) {
int k = findPos(x);
Action mv = new Move(copyToOrig.get(w), copyToOrig.get(z), k);
actions.add(mv);
int oldk = w.positionInParent();
w.getParent().getChildren().remove(oldk);
z.insertChild(w, k);
}
}
else {
if (multiMappingStore.isDstMultiMapped(y))
{
int k = findPos(x);
Action mv = new Move(copyToOrig.get(w), null, k);
actions.add(mv);
}
}
}
}
if (w != null) {
srcInOrder.add(w);
dstInOrder.add(x);
alignChildren(w, x);
}
}
for (Tree w : cpySrc.postOrder()) {
if (!cpyMappings.isSrcMapped(w) && !multiMappingStore.isSrcMultiMapped(copyToOrig.get(w))) {
actions.add(new Delete(copyToOrig.get(w)));
}
else if (!multiMappingStore.isSrcMultiMapped(copyToOrig.get(w)))
{
if (cpyMappings.getDstForSrc(w).equals(TreeUtilFunctions.getFakeTreeInstance()))
{
}
else if (!TreeUtilFunctions.getFinalRoot(cpyMappings.getDstForSrc(w)).equals(origDst))
{
Tree a = cpyMappings.getDstForSrc(w);
actions.add(new MoveOut(copyToOrig.get(w),cpyMappings.getDstForSrc(w),findNameByTree(childContextMap,a),+1));
}
}
}
return actions;
}
private void alignChildren(Tree w, Tree x) {
srcInOrder.removeAll(w.getChildren());
dstInOrder.removeAll(x.getChildren());
List s1 = new ArrayList<>();
for (Tree c: w.getChildren())
if (cpyMappings.isSrcMapped(c))
if (x.getChildren().contains(cpyMappings.getDstForSrc(c)))
s1.add(c);
List s2 = new ArrayList<>();
for (Tree c: x.getChildren())
if (cpyMappings.isDstMapped(c))
if (w.getChildren().contains(cpyMappings.getSrcForDst(c)))
s2.add(c);
List lcs = lcs(s1, s2);
for (Mapping m : lcs) {
srcInOrder.add(m.first);
dstInOrder.add(m.second);
}
for (Tree b: s2 ) { // iterate through s2 first, to ensure left-to-right insertions
for (Tree a : s1) {
if (cpyMappings.has(a, b)) {
if (!lcs.contains(new Mapping(a, b))) {
a.getParent().getChildren().remove(a); // remove this node directly.
int k = findPos(b); // find insert position AFTER removing node from old place.
Action mv = new Move(copyToOrig.get(a), copyToOrig.get(w), k);
actions.add(mv);
w.getChildren().add(k, a);
a.setParent(w);
srcInOrder.add(a);
dstInOrder.add(b);
}
}
}
}
}
private int findPos(Tree x) {
Tree y = x.getParent();
List siblings = y.getChildren();
for (Tree c : siblings) {
if (dstInOrder.contains(c)) {
if (c.equals(x)) return 0;
else break;
}
}
int xpos = x.positionInParent();
Tree v = null;
for (int i = 0; i < xpos; i++) {
Tree c = siblings.get(i);
if (dstInOrder.contains(c)) v = c;
}
//if (v == null) throw new RuntimeException("No rightmost sibling in order");
if (v == null) return 0;
Tree u = cpyMappings.getSrcForDst(v);
// siblings = u.getParent().getChildren();
// int upos = siblings.indexOf(u);
int upos = u.positionInParent();
// int r = 0;
// for (int i = 0; i <= upos; i++)
// if (srcInOrder.contains(siblings.get(i))) r++;
return upos + 1;
}
private List lcs(List x, List y) {
int m = x.size();
int n = y.size();
List lcs = new ArrayList<>();
int[][] opt = new int[m + 1][n + 1];
for (int i = m - 1; i >= 0; i--) {
for (int j = n - 1; j >= 0; j--) {
if (cpyMappings.getSrcForDst(y.get(j)).equals(x.get(i))) opt[i][j] = opt[i + 1][j + 1] + 1;
else opt[i][j] = Math.max(opt[i + 1][j], opt[i][j + 1]);
}
}
int i = 0, j = 0;
while (i < m && j < n) {
if (cpyMappings.getSrcForDst(y.get(j)).equals(x.get(i))) {
lcs.add(new Mapping(x.get(i), y.get(j)));
i++;
j++;
} else if (opt[i + 1][j] >= opt[i][j + 1]) i++;
else j++;
}
return lcs;
}
public String findNameByTree(Map contextMap, Tree t) {
for (Map.Entry stringTreeContextEntry : contextMap.entrySet()) {
if (stringTreeContextEntry.getValue().getRoot() == TreeUtilFunctions.getFinalRoot(t))
{
return stringTreeContextEntry.getKey();
}
}
return "";
}
}