1436190 - Test additions & refactoring
[phpeclipse.git] / archive / net.sourceforge.phpeclipse.quantum.sql / src / com / quantum / view / SQLQueryView.java
1 package com.quantum.view;
2
3 import java.sql.SQLException;
4 import java.util.ArrayList;
5 import java.util.LinkedList;
6 import java.util.List;
7 import java.util.NoSuchElementException;
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.jface.preference.IPreferenceStore;
13 import org.eclipse.jface.preference.PreferenceConverter;
14 import org.eclipse.jface.util.IPropertyChangeListener;
15 import org.eclipse.jface.util.PropertyChangeEvent;
16 import org.eclipse.jface.viewers.ILabelProvider;
17 import org.eclipse.jface.viewers.ILabelProviderListener;
18 import org.eclipse.jface.viewers.IStructuredContentProvider;
19 import org.eclipse.jface.viewers.Viewer;
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.custom.ExtendedModifyEvent;
22 import org.eclipse.swt.custom.ExtendedModifyListener;
23 import org.eclipse.swt.custom.StyleRange;
24 import org.eclipse.swt.custom.StyledText;
25 import org.eclipse.swt.graphics.Color;
26 import org.eclipse.swt.graphics.Font;
27 import org.eclipse.swt.graphics.FontData;
28 import org.eclipse.swt.graphics.Image;
29 import org.eclipse.swt.layout.GridData;
30 import org.eclipse.swt.layout.GridLayout;
31 import org.eclipse.swt.widgets.Composite;
32 import org.eclipse.swt.widgets.Display;
33 import org.eclipse.ui.IActionBars;
34 import org.eclipse.ui.IWorkbenchActionConstants;
35 import org.eclipse.ui.part.ViewPart;
36
37 import com.quantum.ImageStore;
38 import com.quantum.Messages;
39 import com.quantum.PluginPreferences;
40 import com.quantum.QuantumPlugin;
41 import com.quantum.actions.ExecuteAction;
42 import com.quantum.actions.ExportQueryAction;
43 import com.quantum.actions.ImportQueryAction;
44 import com.quantum.editors.ColorManager;
45 import com.quantum.model.Bookmark;
46 import com.quantum.model.BookmarkCollection;
47 import com.quantum.model.NotConnectedException;
48 import com.quantum.sql.MultiSQLServer;
49 import com.quantum.sql.SQLGrammar;
50 import com.quantum.sql.parser.SQLLexx;
51 import com.quantum.sql.parser.Token;
52 import com.quantum.ui.dialog.ExceptionDisplayDialog;
53 import com.quantum.ui.dialog.SQLExceptionDialog;
54 import com.quantum.util.versioning.VersioningHelper;
55
56 public class SQLQueryView extends ViewPart {
57         private class ClearAction extends Action {
58                 
59                 public ClearAction() {
60                         setImageDescriptor(ImageStore.getImageDescriptor(ImageStore.CLEAR));
61                         setToolTipText(Messages.getString("sqlqueryview.clear"));
62                 }
63
64                 public void run() {
65                         setQuery("");
66                 }
67         }
68
69         private class AutoCommitPreferenceAction extends Action {
70                 
71                 public AutoCommitPreferenceAction() {
72                         super(Messages.getString("SQLQueryView.AutoCommit"));
73                         setToolTipText(Messages.getString("SQLQueryView.AutoCommit"));
74                         setImageDescriptor(ImageStore.getImageDescriptor(ImageStore.AUTOCOMMIT));
75                 }
76                 
77                 public void run() {
78                         setAutoCommitPreference(isChecked());
79                 }
80         }
81         
82         private class RollbackAction extends Action {
83                 public RollbackAction() {
84                         setText(Messages.getString("SQLQueryView.RollBack"));
85                         setToolTipText(Messages.getString("SQLQueryView.RollBack"));
86                 }
87                 
88                 public void run() {
89                 Bookmark[] bookmarks = BookmarkCollection.getInstance().getBookmarks();
90                 for (int i = 0, length = bookmarks == null ? 0 : bookmarks.length; i < length; i++) {
91                         try {
92                                         if (bookmarks[i].isConnected() && !bookmarks[i].getConnection().getAutoCommit()) {
93                                                 MultiSQLServer.getInstance().rollback(bookmarks[i].getConnection());
94                                         }
95                     } catch (SQLException e) {
96                         SQLExceptionDialog.openException(getSite().getShell(), bookmarks[i], e);
97                     } catch (NotConnectedException e) {
98                         ExceptionDisplayDialog.openError(getSite().getShell(), null, null, e);
99                     }
100                         }
101                 }
102         }
103         
104         
105         private class CommitAction extends Action {
106                 public CommitAction() {
107                         setText(Messages.getString("SQLQueryView.Commit"));
108                         setToolTipText(Messages.getString("SQLQueryView.Commit"));
109                 }
110                 
111                 public void run() {
112                 Bookmark[] bookmarks = BookmarkCollection.getInstance().getBookmarks();
113                 for (int i = 0, length = bookmarks == null ? 0 : bookmarks.length; i < length; i++) {
114                         try {
115                                         if (bookmarks[i].isConnected() && !bookmarks[i].getConnection().getAutoCommit()) {
116                                                 MultiSQLServer.getInstance().commit(bookmarks[i].getConnection());
117                                         }
118                     } catch (SQLException e) {
119                         SQLExceptionDialog.openException(getSite().getShell(), bookmarks[i], e);
120                     } catch (NotConnectedException e) {
121                         ExceptionDisplayDialog.openError(getSite().getShell(), null, null, e);
122                     }
123                         }
124                 }
125         }
126         
127         
128         public class LabelProviderImpl implements ILabelProvider {
129                 public Image getImage(Object element) {
130                         return ImageStore.getImage(ImageStore.BOOKMARK);
131                 }
132                 public String getText(Object element) {
133                         if (element instanceof Bookmark) {
134                                 return ((Bookmark) element).getName();
135                         } else {
136                                 return null;
137                         }
138                 }
139                 public void addListener(ILabelProviderListener listener) {
140                 }
141                 public void dispose() {
142                 }
143                 public boolean isLabelProperty(Object element, String property) {
144                         return false;
145                 }
146                 public void removeListener(ILabelProviderListener listener) {
147                 }
148         }
149         public class ContentProviderImpl implements IStructuredContentProvider {
150                 public Object[] getElements(Object inputElement) {
151                         if (inputElement instanceof BookmarkCollection) {
152                                 return ((BookmarkCollection) inputElement).getBookmarks();
153                         } else {
154                                 return null;
155                         }
156                 }
157                 public void dispose() {
158                 }
159                 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
160                 }
161         }
162         
163         private ExecuteAction executeAction;
164         private ImportQueryAction importQueryAction;
165         private ExportQueryAction exportQueryAction;
166         private StyledText widget;
167         private AutoCommitPreferenceAction autoCommitPreferenceAction;
168         private RollbackAction rollbackAction;
169         private CommitAction commitAction;
170         private boolean autoCommitPreference = true;
171         private IPropertyChangeListener listener;
172         private ColorManager colorManager = new ColorManager();
173
174         private SyntaxHighlighter textUpdater = new SyntaxHighlighter(this.colorManager);
175         
176         
177         public SQLQueryView() {
178                 super();
179                 this.listener = new IPropertyChangeListener() {
180                         public void propertyChange(PropertyChangeEvent event) {
181                                 setFont();
182                         }
183                 };
184                 QuantumPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(listener);
185         }
186         
187         public void dispose() {
188                 QuantumPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this.listener);
189                 this.colorManager.dispose();
190                 super.dispose();
191         }
192         
193         public static SQLQueryView getInstance() {
194                 return (SQLQueryView) QuantumPlugin.getDefault().getView("com.quantum.view.sqlqueryview");
195
196         }
197
198         public void createPartControl(org.eclipse.swt.widgets.Composite parent) {
199                 initActions();
200                 
201                 initializeColours(parent);
202                 GridLayout layout = new GridLayout(1, false);
203                 layout.horizontalSpacing = 0;
204                 layout.verticalSpacing = 0;
205                 layout.marginHeight = 0;
206                 layout.marginWidth = 0;
207                 parent.setLayout(layout);
208                 parent.setLayoutData(new GridData(GridData.FILL_BOTH));
209                 
210                 widget = new StyledText(parent, SWT.H_SCROLL | SWT.V_SCROLL);
211                 
212                 setFont();
213
214                 IActionBars bars = this.getViewSite().getActionBars();
215                 bars.setGlobalActionHandler(IWorkbenchActionConstants.CUT, cutAction);
216                 bars.setGlobalActionHandler(IWorkbenchActionConstants.COPY, copyAction);
217                 bars.setGlobalActionHandler(IWorkbenchActionConstants.PASTE, pasteAction);
218                 bars.setGlobalActionHandler(IWorkbenchActionConstants.SELECT_ALL, selectAllAction);
219
220                 widget.setEditable(true);
221                 widget.addExtendedModifyListener(modifyListener);
222
223                 widget.setLayoutData(new GridData(GridData.FILL_BOTH));
224
225                 VersioningHelper.registerActionToKeyBindingService(getSite(), 
226                                 new String[] { "org.eclipse.ui.globalScope", "com.quantum.view.sql" }, 
227                         this.executeAction);
228         }
229
230         private void setFont() {
231                 FontData font = PreferenceConverter.getFontData(
232                                 QuantumPlugin.getDefault().getPreferenceStore(), 
233                                 "quantum.font"); //$NON-NLS-1$
234                 if (font != null && this.widget != null) {
235                         this.widget.setFont(new Font(Display.getCurrent(), font));
236                 }
237         }
238         /**
239          * @param parent
240          */
241         private void initializeColours(Composite parent) {
242             IPreferenceStore store = QuantumPlugin.getDefault().getPreferenceStore();
243
244                 parent.setBackground(this.colorManager.getColor(
245                                 PreferenceConverter.getColor(store, PluginPreferences.BACKGROUND_COLOR)));
246                 this.textUpdater.initializeColours();
247         }
248         
249         private void initActions() {
250
251                 IToolBarManager toolBar = getViewSite().getActionBars().getToolBarManager();
252
253                 executeAction = new ExecuteAction(this);
254                 toolBar.add(this.executeAction);
255                 toolBar.add(new ClearAction());
256                 
257         IActionBars actionBars = getViewSite().getActionBars();
258                 this.importQueryAction = new ImportQueryAction();
259                 this.importQueryAction.init(this);
260         actionBars.getMenuManager().add(this.importQueryAction);
261         this.exportQueryAction = new ExportQueryAction();
262         this.exportQueryAction.init(this);
263         actionBars.getMenuManager().add(this.exportQueryAction);
264         actionBars.getMenuManager().add(new Separator());
265         this.autoCommitPreferenceAction = new AutoCommitPreferenceAction();
266         this.autoCommitPreferenceAction.setChecked(this.autoCommitPreference);
267         actionBars.getMenuManager().add(this.autoCommitPreferenceAction);
268
269         this.rollbackAction = new RollbackAction();
270         actionBars.getMenuManager().add(this.rollbackAction);
271
272         this.commitAction = new CommitAction();
273         actionBars.getMenuManager().add(this.commitAction);
274 }
275
276         /**
277          * Returns the query to be executed. The query is either 1) the 
278          * text currently highlighted/selected in the editor or 2) all of 
279      * the text in the editor. 
280          * @return query string to be executed
281          */
282         public String getQuery() {
283             String query; 
284             
285             if (widget.getSelectionText().length() > 0)
286                 query = widget.getSelectionText();
287             else    
288                 query = widget.getText();
289             
290                 return query;
291         }
292         
293         public void setQuery(String text) {
294                 widget.setText(text);
295         }
296         
297         private class UpdateRequest {
298                 public UpdateRequest(String text, int start, int length) {
299                         this.text = text;
300                         this.start = start;
301                         this.length = length;
302                 }
303                 public String text;
304                 public int start;
305                 public int length;
306         }
307         
308         private class SyntaxHighlighter extends Thread {
309                 
310                 private Color STRING_LITERAL;
311                 private Color KEYWORD;
312                 private Color COMMENT;
313                 private Color NUMERIC;
314                 private Color DEFAULT;
315                 
316                 private boolean running = true;
317                 private LinkedList requests = new LinkedList();
318                 private final ColorManager colorManager;
319                 public SyntaxHighlighter(ColorManager colorManager) {
320                         super();
321                         this.colorManager = colorManager;
322                         
323                         setPriority(Thread.MIN_PRIORITY);
324                         start();
325                 }
326                 public void initializeColours() {
327                     IPreferenceStore store = QuantumPlugin.getDefault().getPreferenceStore();
328
329                         this.DEFAULT = this.colorManager.getColor(
330                                         PreferenceConverter.getColor(store, PluginPreferences.TEXT_COLOR));
331                         this.KEYWORD = this.colorManager.getColor(
332                                         PreferenceConverter.getColor(store, PluginPreferences.KEYWORD_COLOR)); 
333                         this.STRING_LITERAL = this.colorManager.getColor(
334                                         PreferenceConverter.getColor(store, PluginPreferences.STRING_COLOR));
335                         this.COMMENT = this.colorManager.getColor(
336                                         PreferenceConverter.getColor(store, PluginPreferences.COMMENT_COLOR));
337                         this.NUMERIC = this.colorManager.getColor(
338                                         PreferenceConverter.getColor(store, PluginPreferences.NUMERIC_COLOR));
339                         
340                 }
341                 public synchronized void updateText(String text, int start, int length) {
342                         requests.add(new UpdateRequest(text, start, length));
343                         notify();
344                 }
345                 public void run() {
346                         while (running) {
347                                 try {
348                                         synchronized (this) {
349                                                 if (requests.size() <= 0) {
350                                                         wait();
351                                                 } else {
352                                                         Thread.sleep(10);
353                                                 }
354                                         }
355                                         UpdateRequest request = (UpdateRequest) requests.removeFirst();
356                                         String text = request.text.toUpperCase();
357                                         //int dirtyStart = request.start;
358                                         //int dirtyEnd = request.start + request.length;
359                                         StyleRange styleRange;
360                                         List tokens = SQLLexx.parse(text);
361                                         List styles = new ArrayList();
362                                         int min = Integer.MAX_VALUE;
363                                         int max = 0;
364                                         for (int i = 0; i < tokens.size(); i++) {
365                                                 Token t = (Token) tokens.get(i);
366                                                 String value = t.getValue();
367                                                 int start = t.getStart();
368                                                 int length = t.getEnd() - t.getStart();
369                                                 styleRange = new StyleRange();
370                                                 styleRange.start = start;
371                                                 styleRange.length = value.length();
372                                                 styleRange.fontStyle = SWT.NULL;
373                                                 styleRange.foreground = DEFAULT;
374                                                 //boolean upper = start <= dirtyEnd && start >= dirtyStart;
375                                                 //boolean lower = ((start + length) >= dirtyStart && (start + length) <= dirtyEnd);
376                                                 //boolean both = (start <= dirtyStart && (start + length) >= dirtyEnd);
377                                                 //if (upper || lower || both) {
378                                                 if (true) { // Let's update the whole text, as some comment changes can alter everything
379                                                         min = Math.min(start, min);
380                                                         max = Math.max(max, start + length);
381                                                         if (t.getType() == Token.IDENTIFIER) {
382                                                                 boolean keyword = false;
383                                                                 for (int index = 0; index < SQLGrammar.KEYWORDS.length; index++) {
384                                                                         if (value.equals(SQLGrammar.KEYWORDS[index])) {
385                                                                                 keyword = true;
386                                                                         }
387                                                                 }
388                                                                 if (keyword) {
389                                                                         styleRange.fontStyle = SWT.BOLD;
390                                                                         styleRange.foreground = KEYWORD;
391                                                                 } else {
392                                                                         styleRange.foreground = DEFAULT;
393                                                                 }
394                                                                 styles.add(styleRange);
395                                                         } else if (t.getType() == Token.COMMENT) {
396                                                                 styleRange.foreground = COMMENT;
397                                                                 styles.add(styleRange);
398                                                         } else if (t.getType() == Token.LITERAL) {
399                                                                 styleRange.foreground = STRING_LITERAL;
400                                                                 styles.add(styleRange);
401                                                         } else if (t.getType() == Token.NUMERIC) {
402                                                                 styleRange.foreground = NUMERIC;
403                                                                 styles.add(styleRange);
404                                                         } else {
405                                                                 styles.add(styleRange);
406                                                         }
407                                                 }
408                                         }
409                                         StyleRange[] ranges = 
410                                                         (StyleRange[]) styles.toArray(new StyleRange[styles.size()]);
411                                         if (max >= 0 && ranges.length > 0) {
412                                                 setStyles(ranges, min, max - min);
413                                         }
414                                 } catch (NoSuchElementException e) {
415                                         // ignore a missing request
416                                 } catch (InterruptedException e) {
417                                         // ignore any interruptions
418                                 }
419                         }
420                 }
421         }
422         public void setStyles(final StyleRange[] styles, final int start, final int length) {
423                 getViewSite().getShell().getDisplay().asyncExec(new Runnable() {
424                         public void run() {
425                                 try {
426                                         for (int i = 0; i < styles.length; i++) {
427                                                 widget.setStyleRange(styles[i]);
428                                         }
429                                 } catch (Throwable t) {
430                                         System.out.println("Error with styles: " + t.getClass().toString()); //$NON-NLS-1$
431                                         // ignore any errors
432                                 }
433                         }
434                 });
435         }
436         
437         ExtendedModifyListener modifyListener = new ExtendedModifyListener() {
438                 public void modifyText(ExtendedModifyEvent event) {
439                         textUpdater.updateText(getQuery(), event.start, event.length);
440                 }
441         };
442                 
443         private Action cutAction = new Action() {
444                 public void run() {
445                         widget.cut();
446                 }
447         };
448         private Action copyAction = new Action() {
449                 public void run() {
450                         widget.copy();
451                 }
452         };
453         private Action pasteAction = new Action() {
454                 public void run() {
455                         widget.paste();
456                 }
457         };
458         private Action selectAllAction = new Action() {
459                 public void run() {
460                         widget.selectAll();
461                 }
462         };
463
464         public void setFocus() {
465         }
466         public boolean isAutoCommitPreference() {
467                 return this.autoCommitPreference;
468         }
469         public void setAutoCommitPreference(boolean autoCommitPreference) {
470                 this.autoCommitPreference = autoCommitPreference;
471         }
472 }