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 | 44148 | jjdelcerro | 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 | 44207 | jjdelcerro | 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 | 44148 | jjdelcerro | 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 | 44207 | jjdelcerro | import org.gvsig.expressionevaluator.Function; |
31 | 44148 | jjdelcerro | import org.gvsig.expressionevaluator.MutableSymbolTable; |
32 | import org.gvsig.expressionevaluator.swing.ExpressionBuilderConfig; |
||
33 | import org.gvsig.tools.ToolsLocator; |
||
34 | 44207 | jjdelcerro | import org.gvsig.tools.exception.BaseException; |
35 | 44148 | jjdelcerro | 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 | 44207 | jjdelcerro | import org.gvsig.tools.visitor.VisitCanceledException; |
42 | import org.gvsig.tools.visitor.Visitor; |
||
43 | 44148 | jjdelcerro | |
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 | 44191 | jjdelcerro | private final JTextComponent text; |
54 | 44259 | jjdelcerro | private final ExpressionBuilderConfig builderConfig; |
55 | 44148 | jjdelcerro | |
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 | 44259 | jjdelcerro | this.builderConfig = config;
|
73 | 44148 | jjdelcerro | 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 | 44259 | jjdelcerro | if( this.text == null || this.builderConfig == null ) { |
166 | 44148 | jjdelcerro | 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 | 44207 | jjdelcerro | final Mutable<String> theTip = new MutableObject<>(null); |
186 | expression.setSQLCompatible(false);
|
||
187 | 44259 | jjdelcerro | if (this.builderConfig.getPreviewSymbolTable() == null) { |
188 | 44148 | jjdelcerro | 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 | 44259 | jjdelcerro | Object theValue = expression.execute(this.builderConfig.getPreviewSymbolTable()); |
199 | 44148 | jjdelcerro | this.setPreview(theValue);
|
200 | } catch (ExpressionRuntimeException ex) {
|
||
201 | 44207 | jjdelcerro | theTip.setValue(ex.getTip()); |
202 | 44148 | jjdelcerro | 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 | 44259 | jjdelcerro | if( this.builderConfig.getPreferences().isSQLCompatible() ) { |
208 | 44207 | jjdelcerro | 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 | 44259 | jjdelcerro | if( builderConfig.getPreviewSymbolTable()!=null && |
223 | !builderConfig.getPreviewSymbolTable().isSQLCompatible(((Identifier)code).name()) ) { |
||
224 | 44207 | jjdelcerro | 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 | 44148 | jjdelcerro | } |
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 | } |