Clover coverage report - PMD - 3.9
Coverage timestamp: Tue Dec 19 2006 09:38:44 EST
file stats: LOC: 296   Methods: 16
NCLOC: 230   Classes: 3
 
 Source file Conditionals Statements Methods TOTAL
DFAPanel.java 0% 0% 0% 0%
coverage
 1    package net.sourceforge.pmd.util.designer;
 2   
 3    import net.sourceforge.pmd.ast.ASTMethodDeclaration;
 4    import net.sourceforge.pmd.ast.SimpleNode;
 5    import net.sourceforge.pmd.dfa.IDataFlowNode;
 6    import net.sourceforge.pmd.dfa.variableaccess.VariableAccess;
 7    import net.sourceforge.pmd.util.LineGetter;
 8    import net.sourceforge.pmd.util.StringUtil;
 9   
 10    import javax.swing.*;
 11    import javax.swing.event.ListSelectionEvent;
 12    import javax.swing.event.ListSelectionListener;
 13    import java.awt.BorderLayout;
 14    import java.awt.Color;
 15    import java.awt.Dimension;
 16    import java.awt.FontMetrics;
 17    import java.awt.Graphics;
 18    import java.util.Iterator;
 19    import java.util.List;
 20   
 21    public class DFAPanel extends JComponent implements ListSelectionListener {
 22   
 23    public static class DFACanvas extends JPanel {
 24   
 25    private static final int NODE_RADIUS = 12;
 26    private static final int NODE_DIAMETER = 2 * NODE_RADIUS;
 27   
 28    private SimpleNode node;
 29   
 30    private int x = 150;
 31    private int y = 50;
 32    private LineGetter lines;
 33   
 34  0 private void addAccessLabel(StringBuffer sb, VariableAccess va) {
 35   
 36  0 if (va.isDefinition()) {
 37  0 sb.append("d(");
 38  0 } else if (va.isReference()) {
 39  0 sb.append("r(");
 40  0 } else if (va.isUndefinition()) {
 41  0 sb.append("u(");
 42    //continue; // eo - the u() entries add a lot of clutter to the report
 43    } else {
 44  0 sb.append("?(");
 45    }
 46   
 47  0 sb.append(va.getVariableName()).append(')');
 48    }
 49   
 50  0 private String childIndicesOf(IDataFlowNode node, String separator) {
 51   
 52  0 List kids = node.getChildren();
 53  0 if (kids.isEmpty()) return "";
 54   
 55  0 StringBuffer sb = new StringBuffer();
 56  0 sb.append(((IDataFlowNode)kids.get(0)).getIndex());
 57   
 58  0 for (int j = 1; j < node.getChildren().size(); j++) {
 59  0 sb.append(separator);
 60  0 sb.append(((IDataFlowNode)kids.get(j)).getIndex());
 61    }
 62  0 return sb.toString();
 63    }
 64   
 65  0 private String[] deriveAccessLabels(List flow) {
 66   
 67  0 if (flow == null || flow.isEmpty()) return StringUtil.EMPTY_STRINGS;
 68   
 69  0 String[] labels = new String[flow.size()];
 70   
 71  0 for (int i=0; i<labels.length; i++) {
 72  0 List access = ((IDataFlowNode) flow.get(i)).getVariableAccess();
 73   
 74  0 if (access == null || access.isEmpty()) {
 75  0 continue; // leave a null at this slot
 76    }
 77   
 78  0 StringBuffer exp = new StringBuffer();
 79  0 addAccessLabel(exp, (VariableAccess) access.get(0));
 80   
 81  0 for (int k = 1; k < access.size(); k++) {
 82  0 exp.append(", ");
 83  0 addAccessLabel(exp, (VariableAccess) access.get(k));
 84    }
 85   
 86  0 labels[i] = exp.toString();
 87    }
 88  0 return labels;
 89    }
 90   
 91  0 private int maxWidthOf(String[] strings, FontMetrics fm) {
 92   
 93  0 int max = 0;
 94  0 String str;
 95   
 96  0 for (int i=0; i<strings.length; i++) {
 97  0 str = strings[i];
 98  0 if (str == null) continue;
 99  0 max = Math.max(max, SwingUtilities.computeStringWidth(fm, str));
 100    }
 101  0 return max;
 102    }
 103   
 104   
 105  0 public void paintComponent(Graphics g) {
 106  0 super.paintComponent(g);
 107   
 108  0 if (node == null) return;
 109   
 110  0 List flow = node.getDataFlowNode().getFlow();
 111  0 FontMetrics fm = g.getFontMetrics();
 112  0 int halfFontHeight = fm.getAscent() / 2;
 113   
 114  0 String[] accessLabels = deriveAccessLabels(flow);
 115  0 int maxAccessLabelWidth = maxWidthOf(accessLabels, fm);
 116   
 117  0 for (int i = 0; i < flow.size(); i++) {
 118  0 IDataFlowNode inode = (IDataFlowNode) flow.get(i);
 119   
 120  0 y = computeDrawPos(inode.getIndex());
 121   
 122  0 g.drawArc(x, y, NODE_DIAMETER, NODE_DIAMETER, 0, 360);
 123  0 g.drawString(lines.getLine(inode.getLine()), x + 100 + maxAccessLabelWidth, y + 15);
 124   
 125    // draw index number centered inside of node
 126  0 String idx = String.valueOf(inode.getIndex());
 127  0 int halfWidth = SwingUtilities.computeStringWidth(fm, idx) / 2;
 128  0 g.drawString(idx, x + NODE_RADIUS - halfWidth, y + NODE_RADIUS + halfFontHeight);
 129   
 130  0 String accessLabel = accessLabels[i];
 131  0 if (accessLabel != null) {
 132  0 g.drawString(accessLabel, x + 70, y + 15);
 133    }
 134   
 135  0 for (int j = 0; j < inode.getChildren().size(); j++) {
 136  0 IDataFlowNode n = (IDataFlowNode) inode.getChildren().get(j);
 137  0 drawMyLine(inode.getIndex(), n.getIndex(), g);
 138    }
 139  0 String childIndices = childIndicesOf(inode, ", ");
 140  0 g.drawString(childIndices, x - 3 * NODE_DIAMETER, y + NODE_RADIUS - 2);
 141    }
 142    }
 143   
 144  0 public void setCode(LineGetter h) {
 145  0 this.lines = h;
 146    }
 147   
 148  0 public void setMethod(SimpleNode node) {
 149  0 this.node = node;
 150    }
 151   
 152  0 private int computeDrawPos(int index) {
 153  0 int z = NODE_RADIUS * 4;
 154  0 return z + index * z;
 155    }
 156   
 157  0 private void drawArrow(Graphics g, int x, int y, int direction) {
 158   
 159  0 final int height = NODE_RADIUS * 2/3;
 160  0 final int width = NODE_RADIUS * 2/3;
 161   
 162  0 switch (direction) {
 163  0 case SwingConstants.NORTH :
 164  0 g.drawLine(x, y, x - width/2, y + height);
 165  0 g.drawLine(x, y, x + width/2, y + height);
 166  0 break;
 167  0 case SwingConstants.SOUTH :
 168  0 g.drawLine(x, y, x - width/2, y - height);
 169  0 g.drawLine(x, y, x + width/2, y - height);
 170  0 break;
 171  0 case SwingConstants.EAST :
 172  0 g.drawLine(x, y, x - height, y - width/2);
 173  0 g.drawLine(x, y, x - height, y + width/2);
 174  0 break;
 175  0 case SwingConstants.WEST :
 176  0 g.drawLine(x, y, x + height, y - width/2);
 177  0 g.drawLine(x, y, x + height, y + width/2);
 178    }
 179    }
 180   
 181  0 private void drawMyLine(int index1, int index2, Graphics g) {
 182  0 int y1 = this.computeDrawPos(index1);
 183  0 int y2 = this.computeDrawPos(index2);
 184   
 185  0 int arrow = 6;
 186   
 187  0 if (index1 < index2) {
 188  0 if (index2 - index1 == 1) {
 189  0 x += NODE_RADIUS;
 190  0 g.drawLine(x, y1 + NODE_DIAMETER, x, y2);
 191    // g.fillRect(x - arrow, y2 - arrow, arrow * 2, arrow * 2);
 192  0 drawArrow(g, x, y2, SwingConstants.SOUTH);
 193  0 x -= NODE_RADIUS;
 194  0 } else if (index2 - index1 > 1) {
 195  0 y1 = y1 + NODE_RADIUS;
 196  0 y2 = y2 + NODE_RADIUS;
 197  0 int n = ((index2 - index1 - 2) * 10) + 10;
 198  0 g.drawLine(x, y1, x - n, y1);
 199  0 g.drawLine(x - n, y1, x - n, y2);
 200  0 g.drawLine(x - n, y2, x, y2);
 201    // g.fillRect(x - arrow, y2 - arrow, arrow * 2, arrow * 2);
 202  0 drawArrow(g, x,y2, SwingConstants.EAST);
 203    }
 204   
 205    } else {
 206  0 if (index1 - index2 > 1) {
 207  0 y1 = y1 + NODE_RADIUS;
 208  0 y2 = y2 + NODE_RADIUS;
 209  0 x = x + NODE_DIAMETER;
 210  0 int n = ((index1 - index2 - 2) * 10) + 10;
 211  0 g.drawLine(x, y1, x + n, y1);
 212  0 g.drawLine(x + n, y1, x + n, y2);
 213  0 g.drawLine(x + n, y2, x, y2);
 214    // g.fillRect(x - arrow, y2 - arrow, arrow * 2, arrow * 2);
 215  0 drawArrow(g, x, y2, SwingConstants.WEST);
 216  0 x = x - NODE_DIAMETER;
 217  0 } else if (index1 - index2 == 1) {
 218  0 y2 = y2 + NODE_DIAMETER;
 219  0 g.drawLine(x + NODE_RADIUS, y2, x + NODE_RADIUS, y1);
 220    // g.fillRect(x + NODE_RADIUS - arrow, y2 - arrow, arrow * 2, arrow * 2);
 221  0 drawArrow(g, x + NODE_RADIUS, y2, SwingConstants.NORTH);
 222    }
 223    }
 224    }
 225    }
 226   
 227    private static class ElementWrapper {
 228    private ASTMethodDeclaration node;
 229   
 230  0 public ElementWrapper(ASTMethodDeclaration node) {
 231  0 this.node = node;
 232    }
 233   
 234  0 public ASTMethodDeclaration getNode() {
 235  0 return node;
 236    }
 237   
 238  0 public String toString() {
 239  0 return node.getMethodName();
 240    }
 241    }
 242   
 243    private DFACanvas dfaCanvas;
 244    private JList nodeList;
 245    private DefaultListModel nodes = new DefaultListModel();
 246   
 247  0 public DFAPanel() {
 248  0 super();
 249   
 250  0 setLayout(new BorderLayout());
 251  0 JPanel leftPanel = new JPanel();
 252   
 253  0 nodeList = new JList(nodes);
 254  0 nodeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
 255  0 nodeList.setFixedCellWidth(150);
 256  0 nodeList.setBorder(BorderFactory.createLineBorder(Color.black));
 257  0 nodeList.addListSelectionListener(this);
 258   
 259  0 leftPanel.add(nodeList);
 260  0 add(leftPanel, BorderLayout.WEST);
 261   
 262  0 dfaCanvas = new DFACanvas();
 263  0 dfaCanvas.setBackground(Color.WHITE);
 264  0 dfaCanvas.setPreferredSize(new Dimension(900, 1400));
 265   
 266  0 JScrollPane scrollPane = new JScrollPane(dfaCanvas);
 267   
 268  0 add(scrollPane, BorderLayout.CENTER);
 269    }
 270   
 271  0 public void valueChanged(ListSelectionEvent event) {
 272  0 ElementWrapper wrapper = null;
 273  0 if (nodes.size() == 1) {
 274  0 wrapper = (ElementWrapper) nodes.get(0);
 275  0 } else if (nodes.isEmpty()) {
 276  0 return;
 277  0 } else if (nodeList.getSelectedValue() == null) {
 278  0 wrapper = (ElementWrapper) nodes.get(0);
 279    } else {
 280  0 wrapper = (ElementWrapper) nodeList.getSelectedValue();
 281    }
 282  0 dfaCanvas.setMethod(wrapper.getNode());
 283  0 dfaCanvas.repaint();
 284    }
 285   
 286  0 public void resetTo(List newNodes, LineGetter lines) {
 287  0 dfaCanvas.setCode(lines);
 288  0 nodes.clear();
 289  0 for (Iterator i = newNodes.iterator(); i.hasNext();) {
 290  0 nodes.addElement(new ElementWrapper((ASTMethodDeclaration) i.next()));
 291    }
 292  0 nodeList.setSelectedIndex(0);
 293  0 dfaCanvas.setMethod((SimpleNode) newNodes.get(0));
 294  0 repaint();
 295    }
 296    }