efdac83bb13729379a799837189eae0946442597
[phpeclipse.git] / archive / net.sourceforge.phpeclipse.quantum.sql / src / com / quantum / view / SQLQueryView.java
1 package com.quantum.view;
2
3 import java.sql.Connection;
4 import java.sql.SQLException;
5 import java.util.LinkedList;
6 import java.util.NoSuchElementException;
7 import java.util.Vector;
8
9 import org.eclipse.jface.action.Action;
10 import org.eclipse.jface.action.IToolBarManager;
11 import org.eclipse.jface.action.Separator;
12 import org.eclipse.swt.SWT;
13 import org.eclipse.swt.custom.ExtendedModifyEvent;
14 import org.eclipse.swt.custom.ExtendedModifyListener;
15 import org.eclipse.swt.custom.StyleRange;
16 import org.eclipse.swt.custom.StyledText;
17 import org.eclipse.swt.events.SelectionEvent;
18 import org.eclipse.swt.events.SelectionListener;
19 import org.eclipse.swt.graphics.Color;
20 import org.eclipse.swt.layout.GridData;
21 import org.eclipse.swt.layout.GridLayout;
22 import org.eclipse.swt.widgets.Composite;
23 import org.eclipse.swt.widgets.ToolBar;
24 import org.eclipse.swt.widgets.ToolItem;
25 import org.eclipse.ui.IActionBars;
26 import org.eclipse.ui.IKeyBindingService;
27 import org.eclipse.ui.IWorkbenchActionConstants;
28 import org.eclipse.ui.part.ViewPart;
29
30 import com.quantum.Messages;
31 import com.quantum.QuantumPlugin;
32 import com.quantum.actions.ExecuteAction;
33 import com.quantum.actions.ExportQueryAction;
34 import com.quantum.actions.ImportQueryAction;
35 import com.quantum.model.Bookmark;
36 import com.quantum.model.NotConnectedException;
37 import com.quantum.sql.MultiSQLServer;
38 import com.quantum.sql.parser.SQLLexx;
39 import com.quantum.sql.parser.Token;
40 import com.quantum.util.versioning.VersioningHelper;
41 import com.quantum.view.bookmark.BookmarkNode;
42 import com.quantum.view.bookmark.BookmarkView;
43
44 public class SQLQueryView extends ViewPart {
45         private class ClearAction extends Action {
46                 
47                 public ClearAction() {
48                         setImageDescriptor(QuantumPlugin.getImageDescriptor("clear.gif"));
49                         setToolTipText(Messages.getString("sqlqueryview.clear"));
50                 }
51
52                 public void run() {
53                         setQuery("");
54                 }
55         }
56
57         private class AutoCommitPreferenceAction extends Action {
58                 
59                 public AutoCommitPreferenceAction() {
60                         super(Messages.getString("SQLQueryView.AutoCommit"), SWT.CHECK);
61                         setToolTipText(Messages.getString("SQLQueryView.AutoCommit"));
62                         setImageDescriptor(QuantumPlugin.getImageDescriptor("autocommit.gif"));
63                 }
64                 
65                 public void run() {
66                         Connection connection = null; 
67                         try { 
68                                 // Get the connection
69                                 connection = getBookmark().getConnection();
70                                 // If connected (else will throw exception and jump out) switchs the state of the
71                                 // autoCommit option of the JDBC driver
72                                 MultiSQLServer.getInstance().setAutoCommit(     connection, isChecked());
73             } catch (NotConnectedException e) {
74                 //Doesn't matter
75             }
76             // Update the bookmark and the buttons
77                         updateAutoCommitState(getBookmark(), connection);
78                 }
79         }
80         
81         
82         private ExecuteAction executeAction;
83         private ImportQueryAction importQueryAction;
84         private ExportQueryAction exportQueryAction;
85         private StyledText widget;
86         private ToolItem autoCommitItem;
87         private ToolItem commitItem;
88         private ToolItem rollbackItem;
89         private Color STRING_LITERAL;
90         private Color KEYWORD;
91         private Color COMMENT;
92         private Color NUMERIC;
93         private Color DEFAULT;
94         private AutoCommitPreferenceAction autoCommitPreferenceAction;
95         
96         public SQLQueryView() {
97                 super();
98         }
99         public void setFocus() {
100                 
101                 String title = "Quantum SQL Query Editor";
102                 Bookmark bookmark = null;
103                 Connection con = null;
104                 if (BookmarkView.getInstance() != null ) {
105                         bookmark = getBookmark();
106                 }
107                 if (bookmark != null) {         
108                         title = bookmark.getName() + " (" + title + ")";
109                         VersioningHelper.setPartName(this, title);
110 //                      setPartName("fred");
111                         try {
112                                 con = bookmark.getConnection();
113                         } catch (NotConnectedException e) {
114                                 // Doesn't matter, "con" remains null
115                         }
116                 }
117                 
118                 updateAutoCommitState(bookmark, con);
119
120                 widget.setFocus();
121
122         }
123         /**
124          * @return
125          */
126         private Bookmark getBookmark() {
127                 if (BookmarkView.getInstance() != null ) {
128                         BookmarkNode node = BookmarkView.getInstance().getCurrentBookmark();
129                         return node == null ? null : node.getBookmark();
130                 } else {
131                         return null;
132                 }
133         }
134         public static SQLQueryView getInstance() {
135                 return (SQLQueryView) QuantumPlugin.getDefault().getView("com.quantum.view.sqlqueryview");
136
137         }
138
139         public void createPartControl(org.eclipse.swt.widgets.Composite parent) {
140                 initActions();
141                 
142                 KEYWORD = new Color(parent.getShell().getDisplay(), 126, 0, 75);
143                 STRING_LITERAL = new Color(parent.getShell().getDisplay(), 0, 0, 255);
144                 COMMENT = new Color(parent.getShell().getDisplay(), 88, 148, 64);
145                 NUMERIC = new Color(parent.getShell().getDisplay(), 255, 0, 0);
146             DEFAULT = new Color(parent.getShell().getDisplay(), 0, 0, 0);
147                 Composite main = new Composite(parent, SWT.NONE);
148                 GridLayout layout = new GridLayout(1, false);
149                 layout.horizontalSpacing = 0;
150                 layout.verticalSpacing = 0;
151                 main.setLayout(layout);
152                 ToolBar toolbar = new ToolBar(main, SWT.HORIZONTAL);
153
154                 commitItem = new ToolItem(toolbar, SWT.PUSH);
155                 commitItem.setImage(QuantumPlugin.getImage("commit.gif")); //$NON-NLS-1$
156                 commitItem.setToolTipText(Messages.getString("SQLQueryView.Commit")); //$NON-NLS-1$
157                 commitItem.addSelectionListener(new SelectionListener() {
158                         public void widgetDefaultSelected(SelectionEvent e) {
159                         }
160                         public void widgetSelected(SelectionEvent event) {
161                 try {
162                                 BookmarkNode node = BookmarkView.getInstance().getCurrentBookmark();
163                                 if (node != null) MultiSQLServer.getInstance().commit(
164                         node.getBookmark().getConnection());
165                 } catch (NotConnectedException e) {
166                     e.printStackTrace();
167                 }
168                         }
169                 });
170                 
171                 rollbackItem = new ToolItem(toolbar, SWT.PUSH);
172                 rollbackItem.setImage(QuantumPlugin.getImage("rollback.gif")); //$NON-NLS-1$
173                 rollbackItem.setToolTipText(Messages.getString("SQLQueryView.RollBack")); //$NON-NLS-1$
174                 rollbackItem.addSelectionListener(new SelectionListener() {
175                         public void widgetDefaultSelected(SelectionEvent event) {
176                         }
177                         public void widgetSelected(SelectionEvent event) {
178                 try {
179                     BookmarkNode node = BookmarkView.getInstance().getCurrentBookmark();
180                     if (node != null) MultiSQLServer.getInstance().rollback(
181                         node.getBookmark().getConnection());
182                 } catch (NotConnectedException e) {
183                     e.printStackTrace();
184                 }
185                         }
186                 });
187                 
188                 autoCommitItem = new ToolItem(toolbar, SWT.CHECK);
189                 autoCommitItem.setImage(QuantumPlugin.getImage("autocommit.gif")); //$NON-NLS-1$
190                 autoCommitItem.setToolTipText(Messages.getString("SQLQueryView.AutoCommit")); //$NON-NLS-1$
191                 autoCommitItem.addSelectionListener(new SelectionListener() {
192                         public void widgetDefaultSelected(SelectionEvent e) {
193                         }
194                         public void widgetSelected(SelectionEvent event) {
195                                 BookmarkNode node = BookmarkView.getInstance().getCurrentBookmark();
196                                 if (node == null) return;
197                                 Connection con = null; 
198                                 try { 
199                                         // Get the connection
200                                         con = node.getBookmark().getConnection();
201                                         // If connected (else will throw exception and jump out) switchs the state of the
202                                         // autoCommit option of the JDBC driver
203                                         MultiSQLServer.getInstance().setAutoCommit(     con, autoCommitItem.getSelection());
204                 } catch (NotConnectedException e) {
205                         //Doesn't matter
206                 }
207                 // Update the bookmark and the buttons
208                                 updateAutoCommitState(node.getBookmark(), con);
209                                 
210                         }
211                 });
212
213                 // TODO: BCH -- this is causing some problems during start-up
214                 Bookmark bookmark = null;
215                 try {
216                         bookmark = getBookmark();
217                 } catch (NullPointerException e) {
218                 }
219                 
220                 if (bookmark == null) {
221                         autoCommitItem.setSelection(true); 
222                 } else {
223                         autoCommitItem.setSelection(bookmark.isAutoCommit());
224                 }
225                 if (autoCommitItem.getSelection()) {
226                         commitItem.setEnabled(false);
227                         rollbackItem.setEnabled(false);
228                 } else {
229                         commitItem.setEnabled(true);
230                         rollbackItem.setEnabled(true);
231                 }
232                 widget = new StyledText(main, SWT.H_SCROLL | SWT.V_SCROLL);
233
234                 IActionBars bars = this.getViewSite().getActionBars();
235                 bars.setGlobalActionHandler(IWorkbenchActionConstants.CUT, cutAction);
236                 bars.setGlobalActionHandler(IWorkbenchActionConstants.COPY, copyAction);
237                 bars.setGlobalActionHandler(IWorkbenchActionConstants.PASTE, pasteAction);
238                 bars.setGlobalActionHandler(IWorkbenchActionConstants.SELECT_ALL, selectAllAction);
239
240                 widget.setEditable(true);
241                 widget.addExtendedModifyListener(modifyListener);
242
243                 GridData gridData = new GridData();
244                 gridData.horizontalAlignment = GridData.FILL;
245                 gridData.verticalAlignment = GridData.FILL;
246                 gridData.grabExcessHorizontalSpace = true;
247                 gridData.grabExcessVerticalSpace = true;
248                 widget.setLayoutData(gridData);
249
250         IKeyBindingService keyBindingService = getSite().getKeyBindingService();
251         // TODO: check the version numbers for this method
252         keyBindingService.setScopes(new String[] {
253             "org.eclipse.ui.globalScope",
254             "com.quantum.view.sql"
255         });
256         keyBindingService.registerAction(this.executeAction);
257         }
258
259         /**
260          * Sets the state of the "Commit", "Rollback" and "autoCommit" buttons
261          * to reflect the situation in the connection
262          */
263         protected void updateAutoCommitState(Bookmark bookmark, Connection connection) {
264                 boolean autoCommit = true;
265                 // Calculate the state of the autoCommit option
266                 if (connection != null)
267                 {
268                         // If we have a connection, the autoCommit state is that of the connection
269                         try {
270                                 autoCommit = connection.getAutoCommit();
271                         } catch (SQLException e) {
272                                 // Doesn't matter, we take default
273                         }
274                 } else {
275                         // if no connection, we try the autoCommit of the bookmark, or else the default
276                         if (bookmark != null) autoCommit = bookmark.isAutoCommit();
277                 }
278                 // Set the autoCommit state of the bookmark to the calculated
279                 if (bookmark != null) bookmark.setAutoCommit(autoCommit);
280                 // Set the state of the buttons to the correct autoCommit state
281                 autoCommitItem.setSelection(autoCommit);
282                 this.autoCommitPreferenceAction.setChecked(autoCommit);
283                 if (autoCommitItem.getSelection()) {
284                         commitItem.setEnabled(false);
285                         rollbackItem.setEnabled(false);
286                 } else {
287                         commitItem.setEnabled(true);
288                         rollbackItem.setEnabled(true);
289                 }
290         }
291         private void initActions() {
292
293                 executeAction = new ExecuteAction();
294                 executeAction.init(this);
295
296                 IToolBarManager toolBar = getViewSite().getActionBars().getToolBarManager();
297                 toolBar.add(this.executeAction);
298 //              toolBar.add(this.importQueryAction);
299 //              toolBar.add(this.exportQueryAction);
300                 
301                 toolBar.add(new ClearAction());
302                 
303         IActionBars actionBars = getViewSite().getActionBars();
304                 this.importQueryAction = new ImportQueryAction();
305                 this.importQueryAction.init(this);
306         actionBars.getMenuManager().add(this.importQueryAction);
307         this.exportQueryAction = new ExportQueryAction();
308         this.exportQueryAction.init(this);
309         actionBars.getMenuManager().add(this.exportQueryAction);
310         actionBars.getMenuManager().add(new Separator());
311         this.autoCommitPreferenceAction = new AutoCommitPreferenceAction();
312         actionBars.getMenuManager().add(this.autoCommitPreferenceAction);
313         }
314
315         public String getQuery() {
316                 return widget.getText();
317         }
318         
319         public void setQuery(String text) {
320                 widget.setText(text);
321         }
322         
323         private String[] keywords = {
324         "ADD", "ALL", "ALTER", "AND", "ANY",
325         "AS", "ASC", "AUTOINCREMENT", "AVA", "BETWEEN",
326         "BINARY", "BIT", "BOOLEAN", "BY", "CREATE",
327         "BYTE", "CHAR", "CHARACTER", "COLUMN", "CONSTRAINT",
328         "COUNT", "COUNTER", "CURRENCY", "DATABASE", "DATE",
329         "DATETIME", "DELETE", "DESC", "DISALLOW", "DISTINCT",
330         "DISTINCTROW", "DOUBLE", "DROP", "EXISTS", "FROM",
331         "FLOAT", "FLOAT4", "FLOAT8", "FOREIGN", "GENERAL",
332         "GROUP", "GUID", "HAVING", "INNER", "INSERT",
333         "IGNORE", "IMP", "IN", "INDEX", "INT", 
334         "INTEGER", "INTEGER1", "INTEGER2", "INTEGER4", "INTO",
335         "IS", "JOIN", "KEY", "LEFT", "LEVEL", 
336         "LIKE", "LOGICAL", "LONG", "LONGBINARY", "LONGTEXT",
337         "MAX", "MEMO", "MIN", "MOD", "MONEY", 
338         "NOT", "NULL", "NUMBER", "NUMERIC", "OLEOBJECT",
339         "ON", "PIVOT", "OPTION", "PRIMARY", "ORDER",
340         "OUTER", "OWNERACCESS", "PARAMETERS", "PERCENT", "REAL",
341         "REFERENCES", "RIGHT", "SELECT", "SET", "SHORT",
342         "SINGLE", "SMALLINT", "SOME", "STDEV", "STDEVP",
343         "STRING", "SUM", "TABLE", "TABLEID", "TEXT", 
344         "TIME", "TIMESTAMP", "TOP", "TRANSFORM", "UNION",
345         "UNIQUE", "UPDATE", "VALUE", "VALUES", "VAR",
346         "VARBINARY", "VARCHAR", "VARP", "WHERE", "WITH",
347         "YESNO" };
348         
349         SyntaxHighlighter textUpdater = new SyntaxHighlighter();
350         
351         private class UpdateRequest {
352                 public UpdateRequest(String text, int start, int length) {
353                         this.text = text;
354                         this.start = start;
355                         this.length = length;
356                 }
357                 public String text;
358                 public int start;
359                 public int length;
360         }
361         
362         private class SyntaxHighlighter extends Thread {
363                 private boolean running = true;
364                 private LinkedList requests = new LinkedList();
365                 public SyntaxHighlighter() {
366                         super();
367                         setPriority(Thread.MIN_PRIORITY);
368                         start();
369                 }
370                 public synchronized void updateText(String text, int start, int length) {
371                         requests.add(new UpdateRequest(text, start, length));
372                         notify();
373                 }
374                 public synchronized void shutdown() {
375                         running = false;
376                         interrupt();
377                 }
378                 public void run() {
379                         while (running) {
380                                 try {
381                                         synchronized (this) {
382                                                 if (requests.size() <= 0) {
383                                                         wait();
384                                                 } else {
385                                                         Thread.sleep(10);
386                                                 }
387                                         }
388                                         UpdateRequest request = (UpdateRequest) requests.removeFirst();
389                                         String text = request.text.toUpperCase();
390                                         //int dirtyStart = request.start;
391                                         //int dirtyEnd = request.start + request.length;
392                                         StyleRange styleRange;
393                                         Vector tokens = SQLLexx.parse(text);
394                                         Vector styles = new Vector();
395                                         int min = Integer.MAX_VALUE;
396                                         int max = 0;
397                                         for (int i = 0; i < tokens.size(); i++) {
398                                                 Token t = (Token) tokens.elementAt(i);
399                                                 String value = t.getValue();
400                                                 int start = t.getStart();
401                                                 int length = t.getEnd() - t.getStart();
402                                                 styleRange = new StyleRange();
403                                                 styleRange.start = start;
404                                                 styleRange.length = value.length();
405                                                 styleRange.fontStyle = SWT.NULL;
406                                                 styleRange.foreground = DEFAULT;
407                                                 //boolean upper = start <= dirtyEnd && start >= dirtyStart;
408                                                 //boolean lower = ((start + length) >= dirtyStart && (start + length) <= dirtyEnd);
409                                                 //boolean both = (start <= dirtyStart && (start + length) >= dirtyEnd);
410                                                 //if (upper || lower || both) {
411                                                 if (true) { // Let's update the whole text, as some comment changes can alter everything
412                                                         min = Math.min(start, min);
413                                                         max = Math.max(max, start + length);
414                                                         if (t.getType() == Token.IDENTIFIER) {
415                                                                 boolean keyword = false;
416                                                                 for (int index = 0; index < keywords.length; index++) {
417                                                                         if (value.equals(keywords[index])) {
418                                                                                 keyword = true;
419                                                                         }
420                                                                 }
421                                                                 if (keyword) {
422                                                                         styleRange.fontStyle = SWT.BOLD;
423                                                                         styleRange.foreground = KEYWORD;
424                                                                 } else {
425                                                                         styleRange.foreground = DEFAULT;
426                                                                 }
427                                                                 styles.addElement(styleRange);
428                                                         } else if (t.getType() == Token.COMMENT) {
429                                                                 styleRange.foreground = COMMENT;
430                                                                 styles.addElement(styleRange);
431                                                         } else if (t.getType() == Token.LITERAL) {
432                                                                 styleRange.foreground = STRING_LITERAL;
433                                                                 styles.addElement(styleRange);
434                                                         } else if (t.getType() == Token.NUMERIC) {
435                                                                 styleRange.foreground = NUMERIC;
436                                                                 styles.addElement(styleRange);
437                                                         } else {
438                                                                 styles.addElement(styleRange);
439                                                         }
440                                                 }
441                                         }
442                                         StyleRange[] ranges = new StyleRange[styles.size()];
443                                         for (int k = 0; k < ranges.length; k++) {
444                                                 ranges[k] = (StyleRange) styles.elementAt(k);
445                                         }
446                                         if (max >= 0 && ranges.length > 0) {
447                                                 setStyles(ranges, min, max - min);
448                                         }
449                                 } catch (NoSuchElementException e) {
450                                         // ignore a missing request
451                                 } catch (InterruptedException e) {
452                                         // ignore any interruptions
453                                 }
454                         }
455                 }
456         }
457         public void setStyles(final StyleRange[] styles, final int start, final int length) {
458                 getViewSite().getShell().getDisplay().asyncExec(new Runnable() {
459                         public void run() {
460                                 try {
461                                         for (int i = 0; i < styles.length; i++) {
462                                                 widget.setStyleRange(styles[i]);
463                                         }
464                                 } catch (Throwable t) {
465                                         System.out.println("Error with styles: " + t.getClass().toString()); //$NON-NLS-1$
466                                         // ignore any errors
467                                 }
468                         }
469                 });
470         }
471         
472         ExtendedModifyListener modifyListener = new ExtendedModifyListener() {
473                 public void modifyText(ExtendedModifyEvent event) {
474                         textUpdater.updateText(getQuery(), event.start, event.length);
475                 }
476         };
477                 
478         private Action cutAction = new Action() {
479                 public void run() {
480                         widget.cut();
481                 }
482         };
483         private Action copyAction = new Action() {
484                 public void run() {
485                         widget.copy();
486                 }
487         };
488         private Action pasteAction = new Action() {
489                 public void run() {
490                         widget.paste();
491                 }
492         };
493         private Action selectAllAction = new Action() {
494                 public void run() {
495                         widget.selectAll();
496                 }
497         };
498 }