Clover coverage report - PMD - 3.9 Coverage timestamp: Tue Dec 19 2006 09:38:44 EST FRAMES NO FRAMES |
file stats: | LOC: | 644 |  | Methods: | 60
| NCLOC: | 514 |  | Classes: | 9
Source file | Conditionals | Statements | Methods | TOTAL
Designer.java | 0% | 0% | 0% | 0% |

1 |  | /**
2 |  | * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3 |  | */
4 |  | package net.sourceforge.pmd.util.designer;
5 |  |
6 |  | import net.sourceforge.pmd.PMD;
7 |  | import net.sourceforge.pmd.RuleContext;
8 |  | import net.sourceforge.pmd.RuleSet;
9 |  | import net.sourceforge.pmd.SourceType;
10 |  | import net.sourceforge.pmd.TargetJDK1_3;
11 |  | import net.sourceforge.pmd.TargetJDK1_4;
12 |  | import net.sourceforge.pmd.TargetJDK1_5;
13 |  | import net.sourceforge.pmd.TargetJDK1_6;
14 |  | import net.sourceforge.pmd.ast.Node;
15 |  | import net.sourceforge.pmd.ast.ParseException;
16 |  | import net.sourceforge.pmd.ast.SimpleNode;
17 |  | import net.sourceforge.pmd.jaxen.DocumentNavigator;
18 |  | import net.sourceforge.pmd.jaxen.MatchesFunction;
19 |  | import net.sourceforge.pmd.jsp.ast.JspCharStream;
20 |  | import net.sourceforge.pmd.jsp.ast.JspParser;
21 |  | import net.sourceforge.pmd.util.NumericConstants;
22 |  | import net.sourceforge.pmd.util.StringUtil;
23 |  | import org.jaxen.BaseXPath;
24 |  | import org.jaxen.JaxenException;
25 |  | import org.jaxen.XPath;
26 |  |
27 |  | import javax.swing.*;
28 |  | import javax.swing.event.*;
29 |  | import javax.swing.text.JTextComponent;
30 |  | import javax.swing.tree.DefaultTreeCellRenderer;
31 |  | import javax.swing.tree.DefaultTreeModel;
32 |  | import javax.swing.tree.TreeNode;
33 |  | import javax.swing.tree.TreePath;
34 |  | import javax.swing.undo.*;
35 |  | import java.awt.BorderLayout;
36 |  | import java.awt.Color;
37 |  | import java.awt.Component;
38 |  | import java.awt.Dimension;
39 |  | import java.awt.Font;
40 |  | import java.awt.FontMetrics;
41 |  | import java.awt.Graphics;
42 |  | import java.awt.Toolkit;
43 |  | import java.awt.datatransfer.Clipboard;
44 |  | import java.awt.datatransfer.ClipboardOwner;
45 |  | import java.awt.datatransfer.StringSelection;
46 |  | import java.awt.datatransfer.Transferable;
47 |  | import java.awt.event.ActionEvent;
48 |  | import java.awt.event.ActionListener;
49 |  | import java.awt.event.ComponentEvent;
50 |  | import java.awt.event.KeyEvent;
51 |  | import java.io.IOException;
52 |  | import java.io.StringReader;
53 |  | import java.io.StringWriter;
54 |  | import java.lang.reflect.InvocationTargetException;
55 |  | import java.lang.reflect.Method;
56 |  | import java.util.Enumeration;
57 |  | import java.util.Iterator;
58 |  | import java.util.List;
59 |  | import java.util.Vector;
60 |  |
61 |  | public class Designer implements ClipboardOwner {
62 |  |
63 |  | private static final char LABEL_IMAGE_SEPARATOR = ':';
64 |  | private static final Color IMAGE_TEXT_COLOR = Color.BLUE;
65 |  |
66 |  | private interface Parser { public SimpleNode parse(StringReader sr); };
67 |  |
68 |  | private static final Parser jdkParser1_3 = new Parser() {
69 | 0 | public SimpleNode parse(StringReader sr) { return new TargetJDK1_3().createParser(sr).CompilationUnit(); };
70 |  | };
71 |  |
72 |  | private static final Parser jdkParser1_4 = new Parser() {
73 | 0 | public SimpleNode parse(StringReader sr) { return new TargetJDK1_4().createParser(sr).CompilationUnit(); };
74 |  | };
75 |  |
76 |  | private static final Parser jdkParser1_5 = new Parser() {
77 | 0 | public SimpleNode parse(StringReader sr) { return new TargetJDK1_5().createParser(sr).CompilationUnit(); };
78 |  | };
79 |  |
80 |  | private static final Parser jdkParser1_6 = new Parser() {
81 | 0 | public SimpleNode parse(StringReader sr) { return new TargetJDK1_6().createParser(sr).CompilationUnit(); };
82 |  | };
83 |  |
84 |  | private static final Parser jspParser = new Parser() {
85 | 0 | public SimpleNode parse(StringReader sr) { return new JspParser(new JspCharStream(sr)).CompilationUnit(); };
86 |  | };
87 |  |
88 |  | private static final Object[][] sourceTypeSets = new Object[][] {
89 |  | { "JDK 1.3", SourceType.JAVA_13, jdkParser1_3 },
90 |  | { "JDK 1.4", SourceType.JAVA_14, jdkParser1_4 },
91 |  | { "JDK 1.5", SourceType.JAVA_15, jdkParser1_5 },
92 |  | { "JDK 1.6", SourceType.JAVA_16, jdkParser1_6 },
93 |  | { "JSP", SourceType.JSP, jspParser }
94 |  | };
95 |  |
96 |  | private static final int defaultSourceTypeSelectionIndex = 1; // JDK 1.4
97 |  |
98 |  |
99 | 0 | private SimpleNode getCompilationUnit() {
100 |  |
101 | 0 | Parser parser = (Parser)sourceTypeSets[selectedSourceTypeIndex()][2];
102 | 0 | return parser.parse(new StringReader(codeEditorPane.getText()));
103 |  | }
104 |  |
105 | 0 | private SourceType getSourceType() {
106 |  |
107 | 0 | return (SourceType)sourceTypeSets[selectedSourceTypeIndex()][1];
108 |  | }
109 |  |
110 | 0 | private int selectedSourceTypeIndex() {
111 | 0 | for (int i=0; i<sourceTypeMenuItems.length; i++) {
112 | 0 | if (sourceTypeMenuItems[i].isSelected()) return i;
113 |  | }
114 | 0 | throw new RuntimeException("Initial default source type not specified");
115 |  | }
116 |  |
117 |  | private class ExceptionNode implements TreeNode {
118 |  |
119 |  | private Object item;
120 |  | private ExceptionNode[] kids;
121 |  |
122 | 0 | public ExceptionNode(Object theItem) {
123 | 0 | item = theItem;
124 |  |
125 | 0 | if (item instanceof ParseException) createKids();
126 |  | }
127 |  |
128 |  | // each line in the error message becomes a separate tree node
129 | 0 | private void createKids() {
130 |  |
131 | 0 | String message = ((ParseException)item).getMessage();
132 | 0 | String[] lines = StringUtil.substringsOf(message, PMD.EOL);
133 |  |
134 | 0 | kids = new ExceptionNode[lines.length];
135 | 0 | for (int i=0; i<lines.length; i++) {
136 | 0 | kids[i] = new ExceptionNode(lines[i]);
137 |  | }
138 |  | }
139 |  |
140 | 0 | public int getChildCount() { return kids == null ? 0 : kids.length; }
141 | 0 | public boolean getAllowsChildren() {return false; }
142 | 0 | public boolean isLeaf() { return kids == null; }
143 | 0 | public TreeNode getParent() { return null; }
144 | 0 | public TreeNode getChildAt(int childIndex) { return kids[childIndex]; }
145 | 0 | public String label() { return item.toString(); }
146 |  |
147 | 0 | public Enumeration children() {
148 | 0 | Enumeration e = new Enumeration() {
149 |  | int i = 0;
150 | 0 | public boolean hasMoreElements() {
151 | 0 | return kids != null && i < kids.length;
152 |  | }
153 |  |
154 | 0 | public Object nextElement() { return kids[i++]; }
155 |  | };
156 | 0 | return e;
157 |  | }
158 |  |
159 | 0 | public int getIndex(TreeNode node) {
160 | 0 | for (int i=0; i<kids.length; i++) {
161 | 0 | if (kids[i] == node) return i;
162 |  | }
163 | 0 | return -1;
164 |  | }
165 |  | }
166 |  |
167 |  | // Tree node that wraps the AST node for the tree widget and
168 |  | // any possible children they may have.
169 |  | private class ASTTreeNode implements TreeNode {
170 |  |
171 |  | private Node node;
172 |  | private ASTTreeNode parent;
173 |  | private ASTTreeNode[] kids;
174 |  |
175 | 0 | public ASTTreeNode(Node theNode) {
176 | 0 | node = theNode;
177 |  |
178 | 0 | Node prnt = node.jjtGetParent();
179 | 0 | if (prnt != null) parent = new ASTTreeNode(prnt);
180 |  | }
181 |  |
182 | 0 | public int getChildCount() { return node.jjtGetNumChildren(); }
183 | 0 | public boolean getAllowsChildren() { return false; }
184 | 0 | public boolean isLeaf() { return node.jjtGetNumChildren() == 0; }
185 | 0 | public TreeNode getParent() { return parent; }
186 |  |
187 | 0 | public Enumeration children() {
188 |  |
189 | 0 | if (getChildCount() > 0) getChildAt(0); // force it to build kids
190 |  |
191 | 0 | Enumeration e = new Enumeration() {
192 |  | int i = 0;
193 | 0 | public boolean hasMoreElements() {
194 | 0 | return kids != null && i < kids.length;
195 |  | }
196 | 0 | public Object nextElement() { return kids[i++]; }
197 |  | };
198 | 0 | return e;
199 |  | }
200 |  |
201 | 0 | public TreeNode getChildAt(int childIndex) {
202 |  |
203 | 0 | if (kids == null) {
204 | 0 | kids = new ASTTreeNode[node.jjtGetNumChildren()];
205 | 0 | for (int i=0; i<kids.length; i++) {
206 | 0 | kids[i] = new ASTTreeNode(node.jjtGetChild(i));
207 |  | }
208 |  | }
209 | 0 | return kids[childIndex];
210 |  | }
211 |  |
212 | 0 | public int getIndex(TreeNode node) {
213 |  |
214 | 0 | for (int i=0; i<kids.length; i++) {
215 | 0 | if (kids[i] == node) return i;
216 |  | }
217 | 0 | return -1;
218 |  | }
219 |  |
220 | 0 | public String label() {
221 | 0 | if (node instanceof SimpleNode) {
222 | 0 | SimpleNode sn = (SimpleNode)node;
223 | 0 | if (sn.getLabel() != null) {
224 | 0 | return node.toString() + LABEL_IMAGE_SEPARATOR + sn.getLabel();
225 |  | }
226 | 0 | if (sn.getImage() == null) {
227 | 0 | return node.toString();
228 |  | }
229 | 0 | return node.toString() + LABEL_IMAGE_SEPARATOR + sn.getImage();
230 |  | }
231 | 0 | return node.toString();
232 |  | }
233 |  | }
234 |  |
235 |  | // Create our own renderer to ensure we don't show the default icon
236 |  | // and render any node image data in a different colour to hightlight
237 |  | // it.
238 |  |
239 |  | private class ASTCellRenderer extends DefaultTreeCellRenderer {
240 |  |
241 |  | private ASTTreeNode node;
242 |  |
243 | 0 | public Icon getIcon() { return null; };
244 |  |
245 | 0 | public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel,boolean expanded,boolean leaf, int row, boolean hasFocus) {
246 |  |
247 | 0 | if (value instanceof ASTTreeNode) {
248 | 0 | node = (ASTTreeNode)value;
249 |  | }
250 | 0 | return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
251 |  | }
252 |  |
253 |  | // overwrite the image data (if present) in a different colour
254 | 0 | public void paint(Graphics g) {
255 |  |
256 | 0 | super.paint(g);
257 |  |
258 | 0 | if (node == null) return;
259 |  |
260 | 0 | String text = node.label();
261 | 0 | int separatorPos = text.indexOf(LABEL_IMAGE_SEPARATOR);
262 | 0 | if (separatorPos < 0) return;
263 |  |
264 | 0 | String label = text.substring(0, separatorPos+1);
265 | 0 | String image = text.substring(separatorPos+1);
266 |  |
267 | 0 | FontMetrics fm = g.getFontMetrics();
268 | 0 | int width = SwingUtilities.computeStringWidth(fm, label);
269 |  |
270 | 0 | g.setColor(IMAGE_TEXT_COLOR);
271 | 0 | g.drawString(image, width, fm.getMaxAscent());
272 |  | }
273 |  | }
274 |  |
275 |  | // Special tree variant that knows how to retrieve node labels and
276 |  | // provides the ability to expand all nodes at once.
277 |  |
278 |  | private class ASTTreeWidget extends JTree {
279 |  |
280 | 0 | public ASTTreeWidget(Vector items) {
281 | 0 | super(items);
282 |  | }
283 |  |
284 | 0 | public String convertValueToText(Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
285 | 0 | if (value == null) return "";
286 | 0 | if (value instanceof ASTTreeNode) {
287 | 0 | return ((ASTTreeNode)value).label();
288 |  | }
289 | 0 | if (value instanceof ExceptionNode) {
290 | 0 | return ((ExceptionNode)value).label();
291 |  | }
292 | 0 | return value.toString();
293 |  | }
294 |  |
295 | 0 | public void expandAll(boolean expand) {
296 | 0 | TreeNode root = (TreeNode)getModel().getRoot();
297 | 0 | expandAll(new TreePath(root), expand);
298 |  | }
299 |  |
300 | 0 | private void expandAll(TreePath parent, boolean expand) {
301 |  | // Traverse children
302 | 0 | TreeNode node = (TreeNode)parent.getLastPathComponent();
303 | 0 | if (node.getChildCount() >= 0) {
304 | 0 | for (Enumeration e=node.children(); e.hasMoreElements(); ) {
305 | 0 | TreeNode n = (TreeNode)e.nextElement();
306 | 0 | TreePath path = parent.pathByAddingChild(n);
307 | 0 | expandAll(path, expand);
308 |  | }
309 |  | }
310 |  |
311 | 0 | if (expand) {
312 | 0 | expandPath(parent);
313 |  | } else {
314 | 0 | collapsePath(parent);
315 |  | }
316 |  | }
317 |  | }
318 |  |
319 | 0 | private void loadTreeData(TreeNode rootNode) {
320 | 0 | astWidget.setModel(new DefaultTreeModel(rootNode));
321 | 0 | astWidget.expandAll(true);
322 |  | }
323 |  |
324 |  | private class ShowListener implements ActionListener {
325 | 0 | public void actionPerformed(ActionEvent ae) {
326 | 0 | MyPrintStream ps = new MyPrintStream();
327 | 0 | System.setOut(ps);
328 | 0 | TreeNode tn;
329 | 0 | try {
330 | 0 | SimpleNode lastCompilationUnit = getCompilationUnit();
331 | 0 | tn = new ASTTreeNode(lastCompilationUnit);
332 |  | } catch (ParseException pe) {
333 | 0 | tn = new ExceptionNode(pe);
334 |  | }
335 |  |
336 | 0 | loadTreeData(tn);
337 |  | }
338 |  | }
339 |  |
340 |  | private class DFAListener implements ActionListener {
341 | 0 | public void actionPerformed(ActionEvent ae) {
342 |  |
343 | 0 | DFAGraphRule dfaGraphRule = new DFAGraphRule();
344 | 0 | RuleSet rs = new RuleSet();
345 | 0 | SourceType sourceType = getSourceType();
346 | 0 | if (!sourceType.equals(SourceType.JSP)){
347 | 0 | rs.addRule(dfaGraphRule);
348 |  | }
349 | 0 | RuleContext ctx = new RuleContext();
350 | 0 | ctx.setSourceCodeFilename("[no filename]");
351 | 0 | StringReader reader = new StringReader(codeEditorPane.getText());
352 | 0 | PMD pmd = new PMD();
353 | 0 | pmd.setJavaVersion(sourceType);
354 |  |
355 | 0 | try {
356 | 0 | pmd.processFile(reader, rs, ctx);
357 |  | // } catch (PMDException pmde) {
358 |  | // loadTreeData(new ExceptionNode(pmde));
359 |  | } catch (Exception e) {
360 | 0 | e.printStackTrace();
361 |  | }
362 |  |
363 | 0 | List methods = dfaGraphRule.getMethods();
364 | 0 | if (methods != null && !methods.isEmpty()) {
365 | 0 | dfaPanel.resetTo(methods, codeEditorPane);
366 | 0 | dfaPanel.repaint();
367 |  | }
368 |  | }
369 |  | }
370 |  |
371 |  | private class XPathListener implements ActionListener {
372 | 0 | public void actionPerformed(ActionEvent ae) {
373 | 0 | xpathResults.clear();
374 | 0 | if (xpathQueryArea.getText().length() == 0) {
375 | 0 | xpathResults.addElement("XPath query field is empty");
376 | 0 | xpathResultList.repaint();
377 | 0 | codeEditorPane.requestFocus();
378 | 0 | return;
379 |  | }
380 | 0 | SimpleNode c = getCompilationUnit();
381 | 0 | try {
382 | 0 | XPath xpath = new BaseXPath(xpathQueryArea.getText(), new DocumentNavigator());
383 | 0 | for (Iterator iter = xpath.selectNodes(c).iterator(); iter.hasNext();) {
384 | 0 | StringBuffer sb = new StringBuffer();
385 | 0 | Object obj = iter.next();
386 | 0 | if (obj instanceof String) {
387 | 0 | System.out.println("Result was a string: " + ((String) obj));
388 | 0 | } else if (!(obj instanceof Boolean)) {
389 |  | // if it's a Boolean and it's 'false', what does that mean?
390 | 0 | SimpleNode node = (SimpleNode) obj;
391 | 0 | String name = node.getClass().getName().substring(node.getClass().getName().lastIndexOf('.') + 1);
392 | 0 | String line = " at line " + node.getBeginLine();
393 | 0 | sb.append(name).append(line).append(PMD.EOL);
394 | 0 | xpathResults.addElement(sb.toString().trim());
395 |  | }
396 |  | }
397 | 0 | if (xpathResults.isEmpty()) {
398 | 0 | xpathResults.addElement("No matching nodes " + System.currentTimeMillis());
399 |  | }
400 |  | } catch (ParseException pe) {
401 | 0 | xpathResults.addElement(pe.fillInStackTrace().getMessage());
402 |  | } catch (JaxenException je) {
403 | 0 | xpathResults.addElement(je.fillInStackTrace().getMessage());
404 |  | }
405 | 0 | xpathResultList.repaint();
406 | 0 | xpathQueryArea.requestFocus();
407 |  | }
408 |  | }
409 |  |
410 |  | private final CodeEditorTextPane codeEditorPane = new CodeEditorTextPane();
411 |  | private final ASTTreeWidget astWidget = new ASTTreeWidget(new Vector());
412 |  | private DefaultListModel xpathResults = new DefaultListModel();
413 |  | private final JList xpathResultList = new JList(xpathResults);
414 |  | private final JTextArea xpathQueryArea = new JTextArea(15, 30);
415 |  | private final JFrame frame = new JFrame("PMD Rule Designer");
416 |  | private final DFAPanel dfaPanel = new DFAPanel();
417 |  | private final JRadioButtonMenuItem[] sourceTypeMenuItems = new JRadioButtonMenuItem[sourceTypeSets.length];
418 |  |
419 | 0 | public Designer() {
420 | 0 | MatchesFunction.registerSelfInSimpleContext();
421 |  |
422 | 0 | xpathQueryArea.setFont(new Font("Verdana", Font.PLAIN, 16));
423 | 0 | makeTextComponentUndoable(codeEditorPane);
424 | 0 | JSplitPane controlSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(codeEditorPane), createXPathQueryPanel());
425 | 0 | JSplitPane resultsSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, createASTPanel(), createXPathResultPanel());
426 |  |
427 | 0 | JTabbedPane tabbed = new JTabbedPane();
428 | 0 | tabbed.addTab("Abstract Syntax Tree / XPath", resultsSplitPane);
429 | 0 | tabbed.addTab("Data Flow Analysis", dfaPanel);
430 | 0 | try {
431 |  | // Remove when minimal runtime support is >= JDK 1.4
432 | 0 | Method setMnemonicAt = JTabbedPane.class.getMethod("setMnemonicAt", new Class[]{Integer.TYPE, Integer.TYPE});
433 | 0 | if (setMnemonicAt != null) {
434 |  | // // Compatible with >= JDK 1.4
435 |  | // tabbed.setMnemonicAt(0, KeyEvent.VK_A);
436 |  | // tabbed.setMnemonicAt(1, KeyEvent.VK_D);
437 | 0 | setMnemonicAt.invoke(tabbed, new Object[]{NumericConstants.ZERO, new Integer(KeyEvent.VK_A)});
438 | 0 | setMnemonicAt.invoke(tabbed, new Object[]{NumericConstants.ONE, new Integer(KeyEvent.VK_D)});
439 |  | }
440 |  | } catch (NoSuchMethodException nsme) { // Runtime is < JDK 1.4
441 |  | } catch (IllegalAccessException e) { // Runtime is >= JDK 1.4 but there was an error accessing the function
442 | 0 | e.printStackTrace();
443 | 0 | throw new InternalError("Runtime reports to be >= JDK 1.4 yet String.split(java.lang.String) is broken.");
444 |  | } catch (IllegalArgumentException e) {
445 | 0 | e.printStackTrace();
446 | 0 | throw new InternalError("Runtime reports to be >= JDK 1.4 yet String.split(java.lang.String) is broken.");
447 |  | } catch (InvocationTargetException e) { // Runtime is >= JDK 1.4 but there was an error accessing the function
448 | 0 | e.printStackTrace();
449 | 0 | throw new InternalError("Runtime reports to be >= JDK 1.4 yet String.split(java.lang.String) is broken.");
450 |  | }
451 |  |
452 | 0 | JSplitPane containerSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, controlSplitPane, tabbed);
453 | 0 | containerSplitPane.setContinuousLayout(true);
454 |  |
455 | 0 | JMenuBar menuBar = createMenuBar();
456 | 0 | frame.setJMenuBar(menuBar);
457 | 0 | frame.getContentPane().add(containerSplitPane);
458 | 0 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
459 |  |
460 | 0 | Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
461 | 0 | int screenHeight = screenSize.height;
462 | 0 | int screenWidth = screenSize.width;
463 |  |
464 | 0 | frame.pack();
465 | 0 | frame.setSize((screenWidth*3/4),(screenHeight*3/4));
466 | 0 | frame.setLocation((screenWidth -frame.getWidth()) / 2, (screenHeight - frame.getHeight()) / 2);
467 | 0 | frame.setVisible(true);
468 | 0 | resultsSplitPane.setDividerLocation(resultsSplitPane.getMaximumDividerLocation() - (resultsSplitPane.getMaximumDividerLocation() / 2));
469 | 0 | containerSplitPane.setDividerLocation(containerSplitPane.getMaximumDividerLocation() / 2);
470 |  | }
471 |  |
472 | 0 | private JMenuBar createMenuBar() {
473 | 0 | JMenuBar menuBar = new JMenuBar();
474 | 0 | JMenu menu = new JMenu("JDK");
475 | 0 | ButtonGroup group = new ButtonGroup();
476 |  |
477 | 0 | for (int i=0; i<sourceTypeSets.length; i++) {
478 | 0 | JRadioButtonMenuItem button = new JRadioButtonMenuItem(sourceTypeSets[i][0].toString());
479 | 0 | sourceTypeMenuItems[i] = button;
480 | 0 | group.add(button);
481 | 0 | menu.add(button);
482 |  | }
483 | 0 | sourceTypeMenuItems[defaultSourceTypeSelectionIndex].setSelected(true);
484 | 0 | menuBar.add(menu);
485 |  |
486 | 0 | JMenu actionsMenu = new JMenu("Actions");
487 | 0 | JMenuItem copyXMLItem = new JMenuItem("Copy xml to clipboard");
488 | 0 | copyXMLItem.addActionListener(new ActionListener() {
489 | 0 | public void actionPerformed(ActionEvent e) {
490 | 0 | copyXmlToClipboard();
491 |  | }
492 |  | });
493 | 0 | actionsMenu.add(copyXMLItem);
494 | 0 | JMenuItem createRuleXMLItem = new JMenuItem("Create rule XML");
495 | 0 | createRuleXMLItem.addActionListener(new ActionListener() {
496 | 0 | public void actionPerformed(ActionEvent e) {
497 | 0 | createRuleXML();
498 |  | }
499 |  | });
500 | 0 | actionsMenu.add(createRuleXMLItem);
501 | 0 | menuBar.add(actionsMenu);
502 |  |
503 | 0 | return menuBar;
504 |  | }
505 |  |
506 | 0 | private void createRuleXML() {
507 | 0 | CreateXMLRulePanel rulePanel = new CreateXMLRulePanel(xpathQueryArea, codeEditorPane);
508 | 0 | JFrame xmlframe = new JFrame("Create XML Rule");
509 | 0 | xmlframe.setContentPane(rulePanel);
510 | 0 | xmlframe.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
511 | 0 | xmlframe.setSize(new Dimension(600, 700));
512 | 0 | xmlframe.addComponentListener(new java.awt.event.ComponentAdapter() {
513 | 0 | public void componentResized(ComponentEvent e) {
514 | 0 | JFrame tmp = (JFrame)e.getSource();
515 | 0 | if (tmp.getWidth()<600 || tmp.getHeight()<700) {
516 | 0 | tmp.setSize(600, 700);
517 |  | }
518 |  | }
519 |  | });
520 | 0 | int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
521 | 0 | int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
522 | 0 | xmlframe.pack();
523 | 0 | xmlframe.setLocation((screenWidth - xmlframe.getWidth()) / 2, (screenHeight - xmlframe.getHeight()) / 2);
524 | 0 | xmlframe.setVisible(true);
525 |  | }
526 |  |
527 | 0 | private JComponent createASTPanel() {
528 | 0 | astWidget.setCellRenderer(new ASTCellRenderer());
529 | 0 | return new JScrollPane(astWidget);
530 |  | }
531 |  |
532 | 0 | private JComponent createXPathResultPanel() {
533 | 0 | xpathResults.addElement("No results yet");
534 | 0 | xpathResultList.setBorder(BorderFactory.createLineBorder(Color.black));
535 | 0 | xpathResultList.setFixedCellWidth(300);
536 | 0 | JScrollPane scrollPane = new JScrollPane();
537 | 0 | scrollPane.getViewport().setView(xpathResultList);
538 | 0 | return scrollPane;
539 |  | }
540 |  |
541 | 0 | private JPanel createXPathQueryPanel() {
542 | 0 | JPanel p = new JPanel();
543 | 0 | p.setLayout(new BorderLayout());
544 | 0 | xpathQueryArea.setBorder(BorderFactory.createLineBorder(Color.black));
545 | 0 | makeTextComponentUndoable(xpathQueryArea);
546 | 0 | JScrollPane scrollPane = new JScrollPane(xpathQueryArea);
547 | 0 | scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
548 | 0 | scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
549 | 0 | final JButton b = createGoButton();
550 |  |
551 | 0 | p.add(new JLabel("XPath Query (if any)"), BorderLayout.NORTH);
552 | 0 | p.add(scrollPane, BorderLayout.CENTER);
553 | 0 | p.add(b, BorderLayout.SOUTH);
554 |  |
555 | 0 | return p;
556 |  | }
557 |  |
558 | 0 | private JButton createGoButton() {
559 | 0 | JButton b = new JButton("Go");
560 | 0 | b.setMnemonic('g');
561 | 0 | b.addActionListener(new ShowListener());
562 | 0 | b.addActionListener(codeEditorPane);
563 | 0 | b.addActionListener(new XPathListener());
564 | 0 | b.addActionListener(new DFAListener());
565 | 0 | return b;
566 |  | }
567 |  |
568 | 0 | private static void makeTextComponentUndoable(JTextComponent textConponent) {
569 | 0 | final UndoManager undoManager = new UndoManager();
570 | 0 | textConponent.getDocument().addUndoableEditListener(new UndoableEditListener() {
571 | 0 | public void undoableEditHappened(
572 |  | UndoableEditEvent evt) {
573 | 0 | undoManager.addEdit(evt.getEdit());
574 |  | }
575 |  | });
576 | 0 | ActionMap actionMap = textConponent.getActionMap();
577 | 0 | InputMap inputMap = textConponent.getInputMap();
578 | 0 | actionMap.put("Undo", new AbstractAction("Undo") {
579 | 0 | public void actionPerformed(ActionEvent evt) {
580 | 0 | try {
581 | 0 | if (undoManager.canUndo()) {
582 | 0 | undoManager.undo();
583 |  | }
584 |  | } catch (CannotUndoException e) {
585 |  | }
586 |  | }
587 |  | });
588 | 0 | inputMap.put(KeyStroke.getKeyStroke("control Z"), "Undo");
589 |  |
590 | 0 | actionMap.put("Redo", new AbstractAction("Redo") {
591 | 0 | public void actionPerformed(ActionEvent evt) {
592 | 0 | try {
593 | 0 | if (undoManager.canRedo()) {
594 | 0 | undoManager.redo();
595 |  | }
596 |  | } catch (CannotRedoException e) {
597 |  | }
598 |  | }
599 |  | });
600 | 0 | inputMap.put(KeyStroke.getKeyStroke("control Y"), "Redo");
601 |  | }
602 |  |
603 | 0 | public static void main(String[] args) {
604 | 0 | new Designer();
605 |  | }
606 |  |
607 | 0 | private final void copyXmlToClipboard() {
608 | 0 | if (codeEditorPane.getText() != null && codeEditorPane.getText().trim().length() > 0) {
609 | 0 | String xml = "";
610 | 0 | SimpleNode cu = getCompilationUnit();
611 | 0 | if (cu != null) {
612 | 0 | try {
613 | 0 | xml = getXmlString(cu);
614 |  | } catch (IOException e) {
615 | 0 | e.printStackTrace();
616 | 0 | xml = "Error trying to construct XML representation";
617 |  | }
618 |  | }
619 | 0 | Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(xml), this);
620 |  | }
621 |  | }
622 |  |
623 |  | /**
624 |  | * Returns an unformatted xml string (without the declaration)
625 |  | *
626 |  | * @param node
627 |  | * @return String
628 |  | * @throws java.io.IOException
629 |  | */
630 | 0 | private String getXmlString(SimpleNode node) throws IOException {
631 |  | /*
632 |  | StringWriter writer = new StringWriter();
633 |  | XMLSerializer xmlSerializer = new XMLSerializer(writer, new OutputFormat("XML", "UTF-8", true));
634 |  | xmlSerializer.asDOMSerializer();
635 |  | xmlSerializer.serialize(node.asXml());
636 |  | return writer.toString();
637 |  | */
638 | 0 | return "FIXME"; // FIXME
639 |  | }
640 |  |
641 | 0 | public void lostOwnership(Clipboard clipboard, Transferable contents) {
642 |  | }
643 |  | }
644 |  |