View Javadoc
1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.dfa;
5   
6   import java.util.ArrayList;
7   import java.util.BitSet;
8   import java.util.List;
9   import java.util.StringTokenizer;
10  
11  import net.sourceforge.pmd.lang.ast.Node;
12  
13  /**
14   * @author raik
15   *         <p/>
16   *         Each data flow contains a set of DataFlowNodes.
17   */
18  public abstract class AbstractDataFlowNode implements DataFlowNode {
19  
20      protected Node node;
21  
22      protected List<DataFlowNode> parents = new ArrayList<>();
23      protected List<DataFlowNode> children = new ArrayList<>();
24      protected BitSet type = new BitSet();
25      protected List<VariableAccess> variableAccess = new ArrayList<>();
26      protected List<DataFlowNode> dataFlow;
27      protected int line;
28  
29      public AbstractDataFlowNode(List<DataFlowNode> dataFlow) {
30  	this.dataFlow = dataFlow;
31  	if (!this.dataFlow.isEmpty()) {
32  	    DataFlowNode parent = this.dataFlow.get(this.dataFlow.size() - 1);
33  	    parent.addPathToChild(this);
34  	}
35  	this.dataFlow.add(this);
36      }
37  
38      public AbstractDataFlowNode(List<DataFlowNode> dataFlow, Node node) {
39  	this(dataFlow);
40  
41  	this.node = node;
42  	node.setDataFlowNode(this);
43  	this.line = node.getBeginLine();
44      }
45  
46      public void addPathToChild(DataFlowNode child) {
47  	DataFlowNode thisChild = child;
48  	// TODO - throw an exception if already contained in children list?
49  	if (!this.children.contains(thisChild) || this.equals(thisChild)) {
50  	    this.children.add(thisChild);
51  	    thisChild.getParents().add(this);
52  	}
53      }
54  
55      public boolean removePathToChild(DataFlowNode child) {
56  	DataFlowNode thisChild = child;
57  	thisChild.getParents().remove(this);
58  	return this.children.remove(thisChild);
59      }
60  
61      public void reverseParentPathsTo(DataFlowNode destination) {
62  	while (!parents.isEmpty()) {
63  	    DataFlowNode parent = parents.get(0);
64  	    parent.removePathToChild(this);
65  	    parent.addPathToChild(destination);
66  	}
67      }
68  
69      public int getLine() {
70  	return this.line;
71      }
72  
73      public void setType(int type) {
74  	this.type.set(type);
75      }
76  
77      public boolean isType(int intype) {
78  	try {
79  	    return type.get(intype);
80  	} catch (IndexOutOfBoundsException e) {
81  	    e.printStackTrace();
82  	}
83  	return false;
84      }
85  
86      public Node getNode() {
87  	return this.node;
88      }
89  
90      public List<DataFlowNode> getChildren() {
91  	return this.children;
92      }
93  
94      public List<DataFlowNode> getParents() {
95  	return this.parents;
96      }
97  
98      public List<DataFlowNode> getFlow() {
99  	return this.dataFlow;
100     }
101 
102     public int getIndex() {
103 	return this.dataFlow.indexOf(this);
104     }
105 
106     public void setVariableAccess(List<VariableAccess> variableAccess) {
107 	if (this.variableAccess.isEmpty()) {
108 	    this.variableAccess = variableAccess;
109 	} else {
110 	    this.variableAccess.addAll(variableAccess);
111 	}
112     }
113 
114     public List<VariableAccess> getVariableAccess() {
115 	return this.variableAccess;
116     }
117 
118     @Override
119     public String toString() {
120 	String res = "DataFlowNode: line " + this.getLine() + ", ";
121 	String tmp = type.toString();
122 	String newTmp = "";
123 	for (char c : tmp.toCharArray()) {
124 	    if (c != '{' && c != '}' && c != ' ') {
125 		newTmp += c;
126 	    }
127 	}
128 	for (StringTokenizer st = new StringTokenizer(newTmp, ","); st.hasMoreTokens();) {
129 	    int newTmpInt = Integer.parseInt(st.nextToken());
130 	    res += "(" + stringFromType(newTmpInt) + ")";
131 	}
132 	res += ", " + this.node.getClass().getName().substring(node.getClass().getName().lastIndexOf('.') + 1);
133 	res += node.getImage() == null ? "" : "(" + this.node.getImage() + ")";
134 	return res;
135     }
136 
137     private String stringFromType(int intype) {
138 	return NodeType.stringFromType(intype) ;
139     }
140 
141 }