Skip to content
Snippets Groups Projects
Commit 98cf7c78 authored by Carlos Galindo's avatar Carlos Galindo
Browse files

Moved ObjectTree and ObjectTreeConnection to their own files.

parent f25f0e3c
No related branches found
No related tags found
1 merge request!58Object flow and trees
......@@ -8,7 +8,7 @@ import com.github.javaparser.resolution.UnsolvedSymbolException;
import com.github.javaparser.resolution.declarations.ResolvedClassDeclaration;
import com.github.javaparser.resolution.types.ResolvedReferenceType;
import es.upv.mist.slicing.arcs.Arc;
import es.upv.mist.slicing.nodes.VariableAction.ObjectTree;
import es.upv.mist.slicing.nodes.ObjectTree;
import es.upv.mist.slicing.utils.ASTUtils;
import es.upv.mist.slicing.utils.Utils;
import org.jgrapht.graph.DirectedPseudograph;
......
......@@ -8,8 +8,8 @@ import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclarati
import com.github.javaparser.resolution.types.ResolvedReferenceType;
import com.github.javaparser.utils.Pair;
import es.upv.mist.slicing.nodes.GraphNode;
import es.upv.mist.slicing.nodes.ObjectTree;
import es.upv.mist.slicing.nodes.VariableAction;
import es.upv.mist.slicing.nodes.VariableAction.ObjectTree;
import es.upv.mist.slicing.utils.ASTUtils;
import java.util.LinkedList;
......
......@@ -8,10 +8,10 @@ import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
import es.upv.mist.slicing.graphs.CallGraph;
import es.upv.mist.slicing.graphs.cfg.CFG;
import es.upv.mist.slicing.nodes.GraphNode;
import es.upv.mist.slicing.nodes.ObjectTree;
import es.upv.mist.slicing.nodes.VariableAction;
import es.upv.mist.slicing.nodes.VariableAction.Definition;
import es.upv.mist.slicing.nodes.VariableAction.Movable;
import es.upv.mist.slicing.nodes.VariableAction.ObjectTree;
import es.upv.mist.slicing.nodes.io.ActualIONode;
import es.upv.mist.slicing.nodes.io.FormalIONode;
......
......@@ -10,10 +10,10 @@ import es.upv.mist.slicing.graphs.CallGraph;
import es.upv.mist.slicing.graphs.ExpressionObjectTreeFinder;
import es.upv.mist.slicing.graphs.cfg.CFG;
import es.upv.mist.slicing.nodes.GraphNode;
import es.upv.mist.slicing.nodes.ObjectTree;
import es.upv.mist.slicing.nodes.VariableAction;
import es.upv.mist.slicing.nodes.VariableAction.Definition;
import es.upv.mist.slicing.nodes.VariableAction.Movable;
import es.upv.mist.slicing.nodes.VariableAction.ObjectTree;
import es.upv.mist.slicing.nodes.VariableAction.Usage;
import es.upv.mist.slicing.nodes.io.ActualIONode;
import es.upv.mist.slicing.nodes.io.FormalIONode;
......
package es.upv.mist.slicing.nodes;
import es.upv.mist.slicing.nodes.oo.MemberNode;
import es.upv.mist.slicing.utils.Utils;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ObjectTree implements Cloneable {
private static final String ROOT_NAME = "-root-";
private static final Pattern FIELD_SPLIT = Pattern.compile("^(?<root>(([_0-9A-Za-z]+\\.)*this)|([_0-9A-Za-z]+)|(-root-))(\\.(?<fields>.+))?$");
private final Map<String, ObjectTree> childrenMap = new HashMap<>();
private MemberNode memberNode;
public ObjectTree() {
memberNode = null;
}
private ObjectTree(String memberName, ObjectTree parent) {
this.memberNode = new MemberNode(memberName, parent.memberNode);
}
protected String getMemberName() {
return memberNode == null ? ROOT_NAME : memberNode.getLabel();
}
public MemberNode getMemberNode() {
return memberNode;
}
public void setMemberNode(MemberNode memberNode) {
this.memberNode = memberNode;
}
public boolean hasChildren() {
return !childrenMap.isEmpty();
}
public void addField(String fieldName) {
String members = removeRoot(fieldName);
addNonRootField(members);
}
private void addNonRootField(String members) {
if (members.contains(".")) {
int firstDot = members.indexOf('.');
String first = members.substring(0, firstDot);
String rest = members.substring(firstDot + 1);
childrenMap.computeIfAbsent(first, f -> new ObjectTree(f, this));
childrenMap.get(first).addNonRootField(rest);
} else {
childrenMap.computeIfAbsent(members, f -> new ObjectTree(f, this));
}
}
public void addAll(ObjectTree tree) {
for (Map.Entry<String, ObjectTree> entry : tree.childrenMap.entrySet())
if (childrenMap.containsKey(entry.getKey()))
childrenMap.get(entry.getKey()).addAll(entry.getValue());
else
childrenMap.put(entry.getKey(), entry.getValue().clone(this));
}
/**
* Copies a subtree from source into another subtree in target.
*
* @param source The source of the nodes.
* @param target The tree where nodes will be added
* @param sourcePrefix The prefix to be consumed before copying nodes. Without root.
* @param targetPrefix The prefix to be consumed before copying nodes. Without root.
*/
public static void copyTree(ObjectTree source, ObjectTree target, String sourcePrefix, String targetPrefix) {
ObjectTree a = source.findObjectTreeOfMember(sourcePrefix);
ObjectTree b = target.findObjectTreeOfMember(targetPrefix);
a.addAll(b);
}
ObjectTree findObjectTreeOfMember(String member) {
ObjectTree result = this;
while (!member.isEmpty()) {
int firstDot = member.indexOf('.');
String first, rest;
if (firstDot != -1) {
first = member.substring(0, firstDot);
rest = member.substring(firstDot + 1);
} else {
first = member;
rest = "";
}
result = result.childrenMap.get(first);
member = rest;
}
return result;
}
public boolean hasMember(String member) {
String field = removeRoot(member);
return hasNonRootMember(field);
}
private boolean hasNonRootMember(String members) {
if (members.contains(".")) {
int firstDot = members.indexOf('.');
String first = members.substring(0, firstDot);
String rest = members.substring(firstDot + 1);
return childrenMap.containsKey(first) && childrenMap.get(first).hasNonRootMember(rest);
} else {
return childrenMap.containsKey(members);
}
}
public MemberNode getNodeFor(String member) {
String field = removeRoot(member);
return getNodeForNonRoot(field);
}
MemberNode getNodeForNonRoot(String members) {
if (members.isEmpty()) {
return memberNode;
} else if (members.contains(".")) {
int firstDot = members.indexOf('.');
String first = members.substring(0, firstDot);
String rest = members.substring(firstDot + 1);
assert childrenMap.containsKey(first);
return childrenMap.get(first).getNodeForNonRoot(rest);
} else {
assert childrenMap.containsKey(members);
return childrenMap.get(members).memberNode;
}
}
public boolean isEmpty() {
return childrenMap.isEmpty();
}
public Iterable<String> nameIterable() {
return () -> new Iterator<>() {
final Iterator<ObjectTree> it = treeIterator();
@Override
public boolean hasNext() {
return it.hasNext();
}
@Override
public String next() {
ObjectTree element = it.next();
StringBuilder builder = new StringBuilder();
MemberNode node = element.memberNode;
if (node == null)
return ROOT_NAME;
else
builder.append(node.getLabel());
while (node.getParent() != null && node.getParent() instanceof MemberNode && node.getParent().getLabel().matches("^(USE|DEF|DEC)\\{")) {
node = (MemberNode) node.getParent();
builder.insert(0, '.');
builder.insert(0, node.getLabel());
}
return builder.insert(0, "-root-.").toString();
}
};
}
public Iterable<MemberNode> nodeIterable() {
return () -> new Iterator<>() {
final Iterator<ObjectTree> it = treeIterator();
@Override
public boolean hasNext() {
return it.hasNext();
}
@Override
public MemberNode next() {
return it.next().memberNode;
}
};
}
private Iterator<ObjectTree> treeIterator() {
return new Iterator<>() {
final Set<ObjectTree> remaining = new HashSet<>(childrenMap.values());
Iterator<ObjectTree> childIterator = null;
@Override
public boolean hasNext() {
if (childIterator == null || !childIterator.hasNext())
return !remaining.isEmpty();
else
return true;
}
@Override
public ObjectTree next() {
if (childIterator == null || !childIterator.hasNext()) {
ObjectTree tree = Utils.setPop(remaining);
childIterator = tree.treeIterator();
return tree;
} else {
return childIterator.next();
}
}
};
}
Iterable<ObjectTree> treeIterable() {
return this::treeIterator;
}
@SuppressWarnings("MethodDoesntCallSuperMethod")
@Override
public Object clone() {
ObjectTree clone = new ObjectTree();
for (Map.Entry<String, ObjectTree> entry : childrenMap.entrySet())
clone.childrenMap.put(entry.getKey(), entry.getValue().clone(clone));
return clone;
}
private ObjectTree clone(ObjectTree parent) {
ObjectTree clone = new ObjectTree(getMemberName(), parent);
for (Map.Entry<String, ObjectTree> entry : childrenMap.entrySet())
clone.childrenMap.put(entry.getKey(), entry.getValue().clone(clone));
return clone;
}
public static String removeRoot(String fieldWithRoot) {
Matcher matcher = FIELD_SPLIT.matcher(fieldWithRoot);
if (matcher.matches())
return matcher.group("fields") != null ? matcher.group("fields") : "";
throw new IllegalArgumentException("Field should be of the form <obj>.<field>, <Type>.this.<field>, where <obj> may not contain dots.");
}
public static String removeFields(String fieldWithRoot) {
Matcher matcher = FIELD_SPLIT.matcher(fieldWithRoot);
if (matcher.matches() && matcher.group("root") != null)
return matcher.group("root");
throw new IllegalArgumentException("Field should be of the form <obj>.<field>, <Type>.this.<field>, where <obj> may not contain dots.");
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ObjectTree tree = (ObjectTree) o;
return Objects.equals(getMemberName(), tree.getMemberName()) &&
childrenMap.values().equals(tree.childrenMap.values());
}
@Override
public int hashCode() {
return Objects.hash(getMemberName(), childrenMap);
}
}
package es.upv.mist.slicing.nodes;
import es.upv.mist.slicing.arcs.Arc;
import es.upv.mist.slicing.arcs.pdg.FlowDependencyArc;
import es.upv.mist.slicing.arcs.pdg.ObjectFlowDependencyArc;
import es.upv.mist.slicing.arcs.sdg.ParameterInOutArc;
import es.upv.mist.slicing.graphs.Graph;
import es.upv.mist.slicing.graphs.jsysdg.JSysDG;
import es.upv.mist.slicing.graphs.jsysdg.JSysPDG;
import es.upv.mist.slicing.nodes.oo.MemberNode;
import java.util.function.Supplier;
class ObjectTreeConnection {
protected final VariableAction sourceAction;
protected final VariableAction targetAction;
protected final String sourceMember;
protected final String targetMember;
protected boolean applied = false;
public ObjectTreeConnection(VariableAction sourceAction, VariableAction targetAction, String sourceMember, String targetMember) {
this.sourceAction = sourceAction;
this.targetAction = targetAction;
this.sourceMember = sourceMember;
this.targetMember = targetMember;
}
public void applySDG(JSysDG graph) {
if (!applied) {
connectTrees(graph, ParameterInOutArc::new, ParameterInOutArc.ObjectFlow::new);
applied = true;
}
}
public void applyPDG(JSysPDG graph) {
if (!applied) {
connectTrees(graph, FlowDependencyArc::new, ObjectFlowDependencyArc::new);
applied = true;
}
}
protected void connectTrees(Graph graph, Supplier<Arc> flowSupplier, Supplier<Arc> objFlowSupplier) {
ObjectTree source = sourceAction.getObjectTree().findObjectTreeOfMember(sourceMember);
ObjectTree target = targetAction.getObjectTree().findObjectTreeOfMember(targetMember);
assert sourceMember.isEmpty() || source.getMemberName() != null;
assert targetMember.isEmpty() || target.getMemberName() != null;
GraphNode<?> rootSrc = source.getMemberNode() != null ? source.getMemberNode() : sourceAction.getGraphNode();
GraphNode<?> rootTgt = target.getMemberNode() != null ? target.getMemberNode() : targetAction.getGraphNode();
graph.addEdge(rootSrc, rootTgt, objFlowSupplier.get());
for (ObjectTree tree : target.treeIterable()) {
MemberNode src = source.getNodeForNonRoot(tree.getMemberName());
MemberNode tgt = tree.getMemberNode();
if (tree.hasChildren())
graph.addEdge(src, tgt, objFlowSupplier.get());
else
graph.addEdge(src, tgt, flowSupplier.get());
}
}
}
......@@ -10,22 +10,19 @@ import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
import com.github.javaparser.resolution.types.ResolvedType;
import es.upv.mist.slicing.arcs.Arc;
import es.upv.mist.slicing.arcs.pdg.DataDependencyArc;
import es.upv.mist.slicing.arcs.pdg.FlowDependencyArc;
import es.upv.mist.slicing.arcs.pdg.ObjectFlowDependencyArc;
import es.upv.mist.slicing.arcs.sdg.ParameterInOutArc;
import es.upv.mist.slicing.graphs.Graph;
import es.upv.mist.slicing.graphs.jsysdg.JSysDG;
import es.upv.mist.slicing.graphs.jsysdg.JSysPDG;
import es.upv.mist.slicing.graphs.pdg.PDG;
import es.upv.mist.slicing.nodes.io.CallNode;
import es.upv.mist.slicing.nodes.io.OutputNode;
import es.upv.mist.slicing.nodes.oo.MemberNode;
import es.upv.mist.slicing.utils.ASTUtils;
import es.upv.mist.slicing.utils.Utils;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.function.Supplier;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
......@@ -565,296 +562,4 @@ public abstract class VariableAction {
}
}
public static class ObjectTree implements Cloneable {
private static final String ROOT_NAME = "-root-";
private static final Pattern FIELD_SPLIT = Pattern.compile("^(?<root>(([_0-9A-Za-z]+\\.)*this)|([_0-9A-Za-z]+)|(-root-))(\\.(?<fields>.+))?$");
private final Map<String, ObjectTree> childrenMap = new HashMap<>();
private MemberNode memberNode;
public ObjectTree() {
memberNode = null;
}
private ObjectTree(String memberName, ObjectTree parent) {
this.memberNode = new MemberNode(memberName, parent.memberNode);
}
protected String getMemberName() {
return memberNode == null ? ROOT_NAME : memberNode.getLabel();
}
public MemberNode getMemberNode() {
return memberNode;
}
public void setMemberNode(MemberNode memberNode) {
this.memberNode = memberNode;
}
public void addField(String fieldName) {
String members = removeRoot(fieldName);
addNonRootField(members);
}
private void addNonRootField(String members) {
if (members.contains(".")) {
int firstDot = members.indexOf('.');
String first = members.substring(0, firstDot);
String rest = members.substring(firstDot + 1);
childrenMap.computeIfAbsent(first, f -> new ObjectTree(f, this));
childrenMap.get(first).addNonRootField(rest);
} else {
childrenMap.computeIfAbsent(members, f -> new ObjectTree(f, this));
}
}
public void addAll(ObjectTree tree) {
for (Map.Entry<String, ObjectTree> entry : tree.childrenMap.entrySet())
if (childrenMap.containsKey(entry.getKey()))
childrenMap.get(entry.getKey()).addAll(entry.getValue());
else
childrenMap.put(entry.getKey(), entry.getValue().clone(this));
}
/**
* Copies a subtree from source into another subtree in target.
* @param source The source of the nodes.
* @param target The tree where nodes will be added
* @param sourcePrefix The prefix to be consumed before copying nodes. Without root.
* @param targetPrefix The prefix to be consumed before copying nodes. Without root.
*/
public static void copyTree(ObjectTree source, ObjectTree target, String sourcePrefix, String targetPrefix) {
ObjectTree a = source.findObjectTreeOfMember(sourcePrefix);
ObjectTree b = target.findObjectTreeOfMember(targetPrefix);
a.addAll(b);
}
private ObjectTree findObjectTreeOfMember(String member) {
ObjectTree result = this;
while (!member.isEmpty()) {
int firstDot = member.indexOf('.');
String first, rest;
if (firstDot != -1) {
first = member.substring(0, firstDot);
rest = member.substring(firstDot + 1);
} else {
first = member;
rest = "";
}
result = result.childrenMap.get(first);
member = rest;
}
return result;
}
public boolean hasMember(String member) {
String field = removeRoot(member);
return hasNonRootMember(field);
}
private boolean hasNonRootMember(String members) {
if (members.contains(".")) {
int firstDot = members.indexOf('.');
String first = members.substring(0, firstDot);
String rest = members.substring(firstDot + 1);
return childrenMap.containsKey(first) && childrenMap.get(first).hasNonRootMember(rest);
} else {
return childrenMap.containsKey(members);
}
}
public MemberNode getNodeFor(String member) {
String field = removeRoot(member);
return getNodeForNonRoot(field);
}
private MemberNode getNodeForNonRoot(String members) {
if (members.isEmpty()) {
return memberNode;
} else if (members.contains(".")) {
int firstDot = members.indexOf('.');
String first = members.substring(0, firstDot);
String rest = members.substring(firstDot + 1);
assert childrenMap.containsKey(first);
return childrenMap.get(first).getNodeForNonRoot(rest);
} else {
assert childrenMap.containsKey(members);
return childrenMap.get(members).memberNode;
}
}
public boolean isEmpty() {
return childrenMap.isEmpty();
}
public Iterable<String> nameIterable() {
return () -> new Iterator<>() {
final Iterator<ObjectTree> it = treeIterator();
@Override
public boolean hasNext() {
return it.hasNext();
}
@Override
public String next() {
ObjectTree element = it.next();
StringBuilder builder = new StringBuilder();
MemberNode node = element.memberNode;
if (node == null)
return ROOT_NAME;
else
builder.append(node.getLabel());
while (node.getParent() != null && node.getParent() instanceof MemberNode && node.getParent().getLabel().matches("^(USE|DEF|DEC)\\{")) {
node = (MemberNode) node.getParent();
builder.insert(0, '.');
builder.insert(0, node.getLabel());
}
return builder.insert(0, "-root-.").toString();
}
};
}
public Iterable<MemberNode> nodeIterable() {
return () -> new Iterator<>() {
final Iterator<ObjectTree> it = treeIterator();
@Override
public boolean hasNext() {
return it.hasNext();
}
@Override
public MemberNode next() {
return it.next().memberNode;
}
};
}
private Iterator<ObjectTree> treeIterator() {
return new Iterator<>() {
final Set<ObjectTree> remaining = new HashSet<>(childrenMap.values());
Iterator<ObjectTree> childIterator = null;
@Override
public boolean hasNext() {
if (childIterator == null || !childIterator.hasNext())
return !remaining.isEmpty();
else
return true;
}
@Override
public ObjectTree next() {
if (childIterator == null || !childIterator.hasNext()) {
ObjectTree tree = Utils.setPop(remaining);
childIterator = tree.treeIterator();
return tree;
} else {
return childIterator.next();
}
}
};
}
private Iterable<ObjectTree> treeIterable() {
return this::treeIterator;
}
@SuppressWarnings("MethodDoesntCallSuperMethod")
@Override
public Object clone() {
ObjectTree clone = new ObjectTree();
for (Map.Entry<String, ObjectTree> entry : childrenMap.entrySet())
clone.childrenMap.put(entry.getKey(), entry.getValue().clone(clone));
return clone;
}
private ObjectTree clone(ObjectTree parent) {
ObjectTree clone = new ObjectTree(getMemberName(), parent);
for (Map.Entry<String, ObjectTree> entry : childrenMap.entrySet())
clone.childrenMap.put(entry.getKey(), entry.getValue().clone(clone));
return clone;
}
public static String removeRoot(String fieldWithRoot) {
Matcher matcher = FIELD_SPLIT.matcher(fieldWithRoot);
if (matcher.matches())
return matcher.group("fields") != null ? matcher.group("fields") : "";
throw new IllegalArgumentException("Field should be of the form <obj>.<field>, <Type>.this.<field>, where <obj> may not contain dots.");
}
public static String removeFields(String fieldWithRoot) {
Matcher matcher = FIELD_SPLIT.matcher(fieldWithRoot);
if (matcher.matches() && matcher.group("root") != null)
return matcher.group("root");
throw new IllegalArgumentException("Field should be of the form <obj>.<field>, <Type>.this.<field>, where <obj> may not contain dots.");
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ObjectTree tree = (ObjectTree) o;
return Objects.equals(getMemberName(), tree.getMemberName()) &&
childrenMap.values().equals(tree.childrenMap.values());
}
@Override
public int hashCode() {
return Objects.hash(getMemberName(), childrenMap);
}
}
static class ObjectTreeConnection {
protected final VariableAction sourceAction;
protected final VariableAction targetAction;
protected final String sourceMember;
protected final String targetMember;
protected boolean applied = false;
public ObjectTreeConnection(VariableAction sourceAction, VariableAction targetAction, String sourceMember, String targetMember) {
this.sourceAction = sourceAction;
this.targetAction = targetAction;
this.sourceMember = sourceMember;
this.targetMember = targetMember;
}
public void applySDG(JSysDG graph) {
if (!applied) {
connectTrees(graph, ParameterInOutArc::new, ParameterInOutArc.ObjectFlow::new);
applied = true;
}
}
public void applyPDG(JSysPDG graph) {
if (!applied) {
connectTrees(graph, FlowDependencyArc::new, ObjectFlowDependencyArc::new);
applied = true;
}
}
protected void connectTrees(Graph graph, Supplier<Arc> flowSupplier, Supplier<Arc> objFlowSupplier) {
ObjectTree source = sourceAction.getObjectTree().findObjectTreeOfMember(sourceMember);
ObjectTree target = targetAction.getObjectTree().findObjectTreeOfMember(targetMember);
assert sourceMember.isEmpty() || source.getMemberName() != null;
assert targetMember.isEmpty() || target.getMemberName() != null;
GraphNode<?> rootSrc = source.getMemberNode() != null ? source.getMemberNode() : sourceAction.getGraphNode();
GraphNode<?> rootTgt = target.getMemberNode() != null ? target.getMemberNode() : targetAction.getGraphNode();
graph.addEdge(rootSrc, rootTgt, objFlowSupplier.get());
for (ObjectTree tree : target.treeIterable()) {
MemberNode src = source.getNodeForNonRoot(tree.getMemberName());
MemberNode tgt = tree.getMemberNode();
if (tree.childrenMap.isEmpty())
graph.addEdge(src, tgt, flowSupplier.get());
else
graph.addEdge(src, tgt, objFlowSupplier.get());
}
}
}
}
......@@ -19,7 +19,6 @@ import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParse
import es.upv.mist.slicing.graphs.ClassGraph;
import es.upv.mist.slicing.graphs.ExpressionObjectTreeFinder;
import es.upv.mist.slicing.graphs.GraphNodeContentVisitor;
import es.upv.mist.slicing.nodes.VariableAction.ObjectTree;
import es.upv.mist.slicing.nodes.io.ActualIONode;
import es.upv.mist.slicing.nodes.io.CallNode;
import es.upv.mist.slicing.utils.ASTUtils;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment