Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.expressionevaluator / org.gvsig.expressionevaluator.swing / org.gvsig.expressionevaluator.swing.impl / src / main / java / org / gvsig / expressionevaluator / swing / impl / AbstractAutomaticExpressionChecker.java @ 44644

History | View | Annotate | Download (12.8 KB)

1
package org.gvsig.expressionevaluator.swing.impl;
2

    
3
import java.awt.Color;
4
import java.awt.Dimension;
5
import java.awt.event.ActionEvent;
6
import java.awt.event.ActionListener;
7
import java.awt.event.KeyAdapter;
8
import java.awt.event.KeyEvent;
9
import java.util.Objects;
10
import javax.swing.JEditorPane;
11
import javax.swing.JMenuItem;
12
import javax.swing.JOptionPane;
13
import javax.swing.JPopupMenu;
14
import javax.swing.JScrollPane;
15
import javax.swing.Timer;
16
import javax.swing.event.DocumentEvent;
17
import javax.swing.event.DocumentListener;
18
import javax.swing.text.JTextComponent;
19
import org.apache.commons.lang3.StringUtils;
20
import org.apache.commons.lang3.mutable.Mutable;
21
import org.apache.commons.lang3.mutable.MutableObject;
22
import org.gvsig.expressionevaluator.Code;
23
import org.gvsig.expressionevaluator.Code.Caller;
24
import org.gvsig.expressionevaluator.Code.Identifier;
25
import org.gvsig.expressionevaluator.Expression;
26
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
27
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
28
import org.gvsig.expressionevaluator.ExpressionRuntimeException;
29
import org.gvsig.expressionevaluator.ExpressionSyntaxException;
30
import org.gvsig.expressionevaluator.Function;
31
import org.gvsig.expressionevaluator.MutableSymbolTable;
32
import org.gvsig.expressionevaluator.swing.ExpressionBuilderConfig;
33
import org.gvsig.tools.ToolsLocator;
34
import org.gvsig.tools.exception.BaseException;
35
import org.gvsig.tools.i18n.I18nManager;
36
import org.gvsig.tools.swing.api.ToolsSwingLocator;
37
import org.gvsig.tools.swing.api.ToolsSwingManager;
38
import org.gvsig.tools.swing.api.windowmanager.Dialog;
39
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
40
import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2;
41
import org.gvsig.tools.visitor.VisitCanceledException;
42
import org.gvsig.tools.visitor.Visitor;
43

    
44
/**
45
 *
46
 * @author jjdelcerro
47
 */
48
@SuppressWarnings("UseSpecificCatch")
49
public abstract class AbstractAutomaticExpressionChecker {
50

    
51
    private static final Color COLOR_ERROR = new Color(255,225,232);
52

    
53
    private final JTextComponent text;
54
    private final ExpressionBuilderConfig builderConfig;
55

    
56
    private Color color_ok;
57
    private Timer timerExpression;
58

    
59
    private JMenuItem menuItemShowPreview;
60
    private JMenuItem menuItemShowTip;
61
    private JMenuItem menuItemShowMessage;
62

    
63
    private String message;
64
    protected String tip;
65
    private String preview;
66
    private DocumentListener doclistener;
67
    private KeyAdapter keylistener;
68
    private ActionListener timelistener;
69

    
70
    public AbstractAutomaticExpressionChecker(ExpressionBuilderConfig config, JTextComponent theText) {
71
        this.text = theText;
72
        this.builderConfig = config;
73
        this.initComponents();
74
    }
75

    
76
    private void initComponents() {
77
        final I18nManager i18n = ToolsLocator.getI18nManager();
78
        final ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
79

    
80
        this.color_ok = this.text.getBackground();
81

    
82
        toolsSwingManager.setDefaultPopupMenu(this.text);
83
        toolsSwingManager.addClearButton(this.text);
84

    
85
        JPopupMenu popupMenu = this.text.getComponentPopupMenu();
86
        
87
        this.menuItemShowTip = new JMenuItem(i18n.getTranslation("_Show_tip"));
88
        this.menuItemShowTip.addActionListener(new ActionListener() {
89
            @Override
90
            public void actionPerformed(ActionEvent e) {
91
                if( StringUtils.isBlank(tip) ) {
92
                    return;
93
                }
94
                JOptionPane.showMessageDialog(
95
                        text.getParent(), 
96
                        tip, 
97
                        i18n.getTranslation("Tip"), 
98
                        JOptionPane.INFORMATION_MESSAGE
99
                );
100
            }
101
        });
102
        popupMenu.add(this.menuItemShowTip);
103

    
104
        this.menuItemShowPreview = new JMenuItem(i18n.getTranslation("_Show_preview"));
105
        this.menuItemShowPreview.addActionListener(new ActionListener() {
106
            @Override
107
            public void actionPerformed(ActionEvent e) {
108
                showMessageDialog(
109
                        i18n.getTranslation("_Preview_value"),
110
                        preview
111
                );
112
            }
113
        });
114
        popupMenu.add(this.menuItemShowPreview);
115
        
116
        this.menuItemShowMessage = new JMenuItem(i18n.getTranslation("_Show_message"));
117
        this.menuItemShowMessage.addActionListener(new ActionListener() {
118
            @Override
119
            public void actionPerformed(ActionEvent e) {
120
                showMessageDialog(
121
                        i18n.getTranslation("_Message"),
122
                        message
123
                );
124
            }
125
        });
126
        popupMenu.add(this.menuItemShowMessage);
127

    
128
        this.timelistener = new ActionListener() {
129
            @Override
130
            public void actionPerformed(ActionEvent e) {
131
                doCheckExpression();
132
            }
133
        };
134
        this.doclistener = new DocumentListener() {
135
            @Override
136
            public void insertUpdate(DocumentEvent e) {
137
                timerExpression.restart();
138
            }
139

    
140
            @Override
141
            public void removeUpdate(DocumentEvent e) {
142
                timerExpression.restart();
143
            }
144

    
145
            @Override
146
            public void changedUpdate(DocumentEvent e) {
147
                timerExpression.restart();
148
            }
149
        };
150
        this.keylistener = new KeyAdapter() {
151
            @Override
152
            public void keyPressed(KeyEvent e) {
153
                if (e.getKeyCode() == KeyEvent.VK_C && e.isControlDown()) {
154
                    doCheckExpression();
155
                }
156
            }
157
        };
158
        this.timerExpression = new Timer(3000, this.timelistener);
159
        this.timerExpression.setRepeats(false);
160
        this.text.getDocument().addDocumentListener(this.doclistener);
161
        this.text.addKeyListener(this.keylistener);
162
    }
163
    
164
    private void doCheckExpression() {
165
        if( this.text == null || this.builderConfig == null ) {
166
            return;
167
        }
168
        Expression expression = this.getExpression();
169
        this.setTip(null);
170
        this.setPreview(null);
171
        this.setMessage(JOptionPane.INFORMATION_MESSAGE, null);
172
        if (expression == null) {
173
            return;
174
        }
175
        try {
176
            expression.getCode();
177
            this.setMessage(JOptionPane.INFORMATION_MESSAGE, "");
178
        } catch (ExpressionSyntaxException ex) {
179
            this.setMessage(JOptionPane.ERROR_MESSAGE, ex.getDescription());
180
            return;
181
        } catch (Exception ex) {
182
            this.setMessage(JOptionPane.ERROR_MESSAGE, "Syntax error in expression");
183
            return;
184
        }
185
        final Mutable<String> theTip = new MutableObject<>(null);
186
        expression.setSQLCompatible(false);
187
        if (this.builderConfig.getPreviewSymbolTable() == null) {
188
            try {
189
                ExpressionEvaluatorManager theManager = ExpressionEvaluatorLocator.getManager();
190
                MutableSymbolTable symbolTable = theManager.createSymbolTable();
191
                Object theValue = expression.execute(symbolTable);
192
                this.setPreview(theValue);
193
            } catch (Exception ex) {
194
                this.setMessage(JOptionPane.INFORMATION_MESSAGE, "");
195
            }
196
        } else {
197
            try {
198
                Object theValue = expression.execute(this.builderConfig.getPreviewSymbolTable());
199
                this.setPreview(theValue);
200
            } catch (ExpressionRuntimeException ex) {
201
                theTip.setValue(ex.getTip());
202
                this.setMessage(JOptionPane.ERROR_MESSAGE, "Runtime error. " + ex.getMessage());
203
            } catch (Exception ex) {
204
                this.setMessage(JOptionPane.ERROR_MESSAGE, "Runtime error. " + ex.getMessage());
205
            }
206
        }
207
        if( this.builderConfig.getPreferences().isSQLCompatible() ) {
208
            Code code = expression.getCode();
209
            try {
210
                code.accept(new Visitor() {
211
                    @Override
212
                    public void visit(Object obj) throws VisitCanceledException, BaseException {
213
                        Code code = (Code) obj;
214
                        switch(code.code()) {
215
                            case Code.CALLER:
216
                                Function function = ((Caller)code).function();
217
                                if( function!=null && !function.isSQLCompatible() ) {
218
                                    theTip.setValue(I18N.Avoid_the_use_of_functions_not_compatible_with_SQL_in_this_data_source(function.name()));
219
                                }
220
                                break;
221
                            case Code.IDENTIFIER:
222
                                if( builderConfig.getPreviewSymbolTable()!=null && 
223
                                        !builderConfig.getPreviewSymbolTable().isSQLCompatible(((Identifier)code).name()) ) {
224
                                    theTip.setValue(I18N.Avoid_the_use_of_functions_not_compatible_with_SQL_in_this_data_source(((Identifier)code).name()));
225
                                }
226
                                break;
227
                            case Code.METHOD:
228
                                theTip.setValue(I18N.Avoid_the_use_of_functions_not_compatible_with_SQL_in_this_data_source(((Caller)code).name()));
229
                                break;
230
                        }
231
                    }
232
                });
233
            } catch (BaseException ex) {
234
            }
235
        }
236
        if( !StringUtils.isBlank(theTip.getValue()) ) {
237
            this.setTip(theTip.getValue());
238
        }
239
    }
240

    
241
    protected boolean isTipEnabled() {
242
        return !StringUtils.isBlank(this.tip);
243
    }
244
    
245
    protected boolean isPreviewEnabled() {
246
        return !StringUtils.isBlank(this.preview);
247
    }
248
    
249
    protected boolean isMessageEnabled() {
250
        return !StringUtils.isBlank(this.message);
251
    }
252
    
253
    protected String getTip() {
254
        return this.tip;
255
    }
256

    
257
    protected String getMessage() {
258
        return this.message;
259
    }
260

    
261
    protected String getPreview() {
262
        return this.preview; 
263
    }
264
    
265
    protected void showMessageDialog() {
266
        final I18nManager i18n = ToolsLocator.getI18nManager();
267
        if( this.isMessageEnabled() ) {
268
            this.showMessageDialog(
269
                    i18n.getTranslation("_Message"),
270
                    this.getMessage()
271
            );
272
        } else if( this.isPreviewEnabled()) {
273
            this.showMessageDialog(
274
                    i18n.getTranslation("_Preview_value"),
275
                    this.getPreview()
276
            );
277
        }
278
    }
279
    
280
    protected void showMessageDialog(String title, String msg) {
281
        final I18nManager i18n = ToolsLocator.getI18nManager();
282
        final ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
283

    
284
        JEditorPane textMessage = new JEditorPane();
285
        JScrollPane scroll = new JScrollPane(textMessage);
286
        scroll.setPreferredSize(new Dimension(500, 300));
287
        toolsSwingManager.setDefaultPopupMenu(textMessage);
288
        textMessage.setContentType("text/html");
289
        textMessage.setText("<html>"+msg+"</html>");
290
        textMessage.setCaretPosition(0);
291
        WindowManager_v2 winmgr = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
292
        Dialog dialog = winmgr.createDialog(
293
                scroll,
294
                title, 
295
                null,
296
                WindowManager_v2.BUTTONS_OK
297
        );
298
        dialog.show(WindowManager.MODE.DIALOG);        
299
    }
300
    
301
    protected void setPreview(Object value) {
302
        this.preview = Objects.toString(value, null);
303
        this.text.setToolTipText(
304
                "<html>" + 
305
                StringUtils.abbreviate(Objects.toString(this.preview,""),100) + 
306
                "</html>"
307
        );
308
        this.menuItemShowPreview.setEnabled(this.isPreviewEnabled());
309
        this.text.setBackground(color_ok);
310
    }
311
    
312
    protected void setMessage(int mode, String text) {
313
        this.message = text;
314
        if( StringUtils.isBlank(text) ) {
315
            this.text.setToolTipText("");
316
            this.menuItemShowMessage.setEnabled(false);
317
        } else {
318
            this.text.setToolTipText(
319
                    "<html>" + 
320
                    StringUtils.abbreviate(Objects.toString(text,""),100) + 
321
                    "</html>"
322
            );
323
            this.menuItemShowMessage.setEnabled(true);
324
        }
325
        switch (mode) {
326
            case JOptionPane.INFORMATION_MESSAGE:
327
                this.text.setBackground(color_ok);
328
                break;
329
            case JOptionPane.WARNING_MESSAGE:
330
            case JOptionPane.ERROR_MESSAGE:
331
            default:
332
                this.text.setBackground(COLOR_ERROR);
333
                break;
334
        }
335
    }
336
    
337
    protected void setTip(String theTip) {
338
        this.tip = theTip;
339
        this.menuItemShowTip.setEnabled(this.isTipEnabled());
340
    }
341
    
342
    protected abstract Expression getExpression();
343
}