AbstractDataFlowNode.java
001 /**
002  * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
003  */
004 package net.sourceforge.pmd.lang.dfa;
005 
006 import java.util.ArrayList;
007 import java.util.BitSet;
008 import java.util.HashMap;
009 import java.util.List;
010 import java.util.Map;
011 import java.util.StringTokenizer;
012 
013 import net.sourceforge.pmd.lang.ast.Node;
014 
015 /**
016  @author raik
017  *         <p/>
018  *         Each data flow contains a set of DataFlowNodes.
019  */
020 public abstract class AbstractDataFlowNode implements DataFlowNode {
021 
022     protected Node node;
023     protected Map<Integer, String> typeMap = new HashMap<Integer, String>();
024 
025     protected List<DataFlowNode> parents = new ArrayList<DataFlowNode>();
026     protected List<DataFlowNode> children = new ArrayList<DataFlowNode>();
027     protected BitSet type = new BitSet();
028     protected List<VariableAccess> variableAccess = new ArrayList<VariableAccess>();
029     protected List<DataFlowNode> dataFlow;
030     protected int line;
031 
032     public AbstractDataFlowNode(List<DataFlowNode> dataFlow) {
033   this.dataFlow = dataFlow;
034   if (!this.dataFlow.isEmpty()) {
035       DataFlowNode parent = this.dataFlow.get(this.dataFlow.size() 1);
036       parent.addPathToChild(this);
037   }
038   this.dataFlow.add(this);
039     }
040 
041     public AbstractDataFlowNode(List<DataFlowNode> dataFlow, Node node) {
042   this(dataFlow);
043 
044   this.node = node;
045   node.setDataFlowNode(this);
046   this.line = node.getBeginLine();
047     }
048 
049     public void addPathToChild(DataFlowNode child) {
050   DataFlowNode thisChild = child;
051   // TODO - throw an exception if already contained in children list?
052   if (!this.children.contains(thisChild|| this.equals(thisChild)) {
053       this.children.add(thisChild);
054       thisChild.getParents().add(this);
055   }
056     }
057 
058     public boolean removePathToChild(DataFlowNode child) {
059   DataFlowNode thisChild = child;
060   thisChild.getParents().remove(this);
061   return this.children.remove(thisChild);
062     }
063 
064     public void reverseParentPathsTo(DataFlowNode destination) {
065   while (!parents.isEmpty()) {
066       DataFlowNode parent = parents.get(0);
067       parent.removePathToChild(this);
068       parent.addPathToChild(destination);
069   }
070     }
071 
072     public int getLine() {
073   return this.line;
074     }
075 
076     public void setType(int type) {
077   this.type.set(type);
078     }
079 
080     public boolean isType(int intype) {
081   try {
082       return type.get(intype);
083   catch (IndexOutOfBoundsException e) {
084       e.printStackTrace();
085   }
086   return false;
087     }
088 
089     public Node getNode() {
090   return this.node;
091     }
092 
093     public List<DataFlowNode> getChildren() {
094   return this.children;
095     }
096 
097     public List<DataFlowNode> getParents() {
098   return this.parents;
099     }
100 
101     public List<DataFlowNode> getFlow() {
102   return this.dataFlow;
103     }
104 
105     public int getIndex() {
106   return this.dataFlow.indexOf(this);
107     }
108 
109     public void setVariableAccess(List<VariableAccess> variableAccess) {
110   if (this.variableAccess.isEmpty()) {
111       this.variableAccess = variableAccess;
112   else {
113       this.variableAccess.addAll(variableAccess);
114   }
115     }
116 
117     public List<VariableAccess> getVariableAccess() {
118   return this.variableAccess;
119     }
120 
121     @Override
122     public String toString() {
123   String res = "DataFlowNode: line " this.getLine() ", ";
124   String tmp = type.toString();
125   String newTmp = "";
126   for (char c : tmp.toCharArray()) {
127       if (c != '{' && c != '}' && c != ' ') {
128     newTmp += c;
129       }
130   }
131   for (StringTokenizer st = new StringTokenizer(newTmp, ","); st.hasMoreTokens();) {
132       int newTmpInt = Integer.parseInt(st.nextToken());
133       res += "(" + stringFromType(newTmpInt")";
134   }
135   res += ", " this.node.getClass().getName().substring(node.getClass().getName().lastIndexOf('.'1);
136   res += node.getImage() == null "" "(" this.node.getImage() ")";
137   return res;
138     }
139 
140     private String stringFromType(int intype) {
141   if (typeMap.isEmpty()) {
142       typeMap.put(NodeType.IF_EXPR, "IF_EXPR");
143       typeMap.put(NodeType.IF_LAST_STATEMENT, "IF_LAST_STATEMENT");
144       typeMap.put(NodeType.IF_LAST_STATEMENT_WITHOUT_ELSE, "IF_LAST_STATEMENT_WITHOUT_ELSE");
145       typeMap.put(NodeType.ELSE_LAST_STATEMENT, "ELSE_LAST_STATEMENT");
146       typeMap.put(NodeType.WHILE_LAST_STATEMENT, "WHILE_LAST_STATEMENT");
147       typeMap.put(NodeType.WHILE_EXPR, "WHILE_EXPR");
148       typeMap.put(NodeType.SWITCH_START, "SWITCH_START");
149       typeMap.put(NodeType.CASE_LAST_STATEMENT, "CASE_LAST_STATEMENT");
150       typeMap.put(NodeType.SWITCH_LAST_DEFAULT_STATEMENT, "SWITCH_LAST_DEFAULT_STATEMENT");
151       typeMap.put(NodeType.SWITCH_END, "SWITCH_END");
152       typeMap.put(NodeType.FOR_INIT, "FOR_INIT");
153       typeMap.put(NodeType.FOR_EXPR, "FOR_EXPR");
154       typeMap.put(NodeType.FOR_UPDATE, "FOR_UPDATE");
155       typeMap.put(NodeType.FOR_BEFORE_FIRST_STATEMENT, "FOR_BEFORE_FIRST_STATEMENT");
156       typeMap.put(NodeType.FOR_END, "FOR_END");
157       typeMap.put(NodeType.DO_BEFORE_FIRST_STATEMENT, "DO_BEFORE_FIRST_STATEMENT");
158       typeMap.put(NodeType.DO_EXPR, "DO_EXPR");
159       typeMap.put(NodeType.RETURN_STATEMENT, "RETURN_STATEMENT");
160       typeMap.put(NodeType.BREAK_STATEMENT, "BREAK_STATEMENT");
161       typeMap.put(NodeType.CONTINUE_STATEMENT, "CONTINUE_STATEMENT");
162       typeMap.put(NodeType.LABEL_STATEMENT, "LABEL_STATEMENT");
163       typeMap.put(NodeType.LABEL_LAST_STATEMENT, "LABEL_END");
164       typeMap.put(NodeType.THROW_STATEMENT, "THROW_STATEMENT");
165   }
166   if (!typeMap.containsKey(intype)) {
167       throw new RuntimeException("Couldn't find type id " + intype);
168   }
169   return typeMap.get(intype);
170     }
171 
172 }