svn-gvsig-desktop / tags / v2_0_0_Build_2065 / extensions / extWFS2 / src / org / gvsig / wfs / gui / panels / WFSFilterPanel.java @ 40276
History | View | Annotate | Download (32.8 KB)
1 |
package org.gvsig.wfs.gui.panels; |
---|---|
2 |
|
3 |
import java.awt.Color; |
4 |
import java.awt.event.MouseAdapter; |
5 |
import java.awt.event.MouseEvent; |
6 |
import java.io.ByteArrayInputStream; |
7 |
import java.io.InputStream; |
8 |
import java.text.DateFormat; |
9 |
import java.text.ParseException; |
10 |
import java.util.Comparator; |
11 |
import java.util.HashMap; |
12 |
import java.util.Iterator; |
13 |
import java.util.Map; |
14 |
import java.util.Set; |
15 |
import java.util.StringTokenizer; |
16 |
import java.util.TreeSet; |
17 |
import java.util.Vector; |
18 |
|
19 |
import javax.swing.DefaultListModel; |
20 |
import javax.swing.JOptionPane; |
21 |
import javax.swing.event.DocumentEvent; |
22 |
import javax.swing.event.DocumentListener; |
23 |
import javax.swing.event.TreeSelectionEvent; |
24 |
import javax.swing.event.TreeSelectionListener; |
25 |
import javax.swing.tree.DefaultMutableTreeNode; |
26 |
import javax.swing.tree.DefaultTreeModel; |
27 |
import javax.swing.tree.TreePath; |
28 |
|
29 |
import org.gvsig.andami.PluginServices; |
30 |
import org.gvsig.andami.messages.NotificationManager; |
31 |
import org.gvsig.app.gui.filter.ExpressionDataSource; |
32 |
import org.gvsig.app.gui.filter.FilterException; |
33 |
import org.gvsig.app.sqlQueryValidation.SQLQueryValidation; |
34 |
import org.gvsig.fmap.dal.DataStore; |
35 |
import org.gvsig.fmap.dal.feature.Feature; |
36 |
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor; |
37 |
import org.gvsig.fmap.dal.feature.FeatureStore; |
38 |
import org.gvsig.gui.beans.Messages; |
39 |
import org.gvsig.gui.beans.filterPanel.filterQueryPanel.FilterQueryJPanel; |
40 |
import org.gvsig.gui.beans.panelGroup.IPanelGroup; |
41 |
import org.gvsig.remoteclient.wfs.WFSFeatureField; |
42 |
import org.gvsig.tools.dataTypes.DataTypes; |
43 |
import org.gvsig.tools.dispose.DisposableIterator; |
44 |
import org.gvsig.utils.stringNumberUtilities.StringNumberUtilities; |
45 |
import org.gvsig.wfs.gui.panels.fieldstree.FieldsTreeTableModel; |
46 |
import org.gvsig.wfs.gui.panels.model.WFSSelectedFeature; |
47 |
import org.gvsig.xmlschema.lib.api.som.IXSElementDeclaration; |
48 |
import org.slf4j.Logger; |
49 |
import org.slf4j.LoggerFactory; |
50 |
|
51 |
import Zql.ZExp; |
52 |
import Zql.ZqlParser; |
53 |
|
54 |
|
55 |
|
56 |
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
|
57 |
*
|
58 |
* Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
|
59 |
*
|
60 |
* This program is free software; you can redistribute it and/or
|
61 |
* modify it under the terms of the GNU General Public License
|
62 |
* as published by the Free Software Foundation; either version 2
|
63 |
* of the License, or (at your option) any later version.
|
64 |
*
|
65 |
* This program is distributed in the hope that it will be useful,
|
66 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
67 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
68 |
* GNU General Public License for more details.
|
69 |
*
|
70 |
* You should have received a copy of the GNU General Public License
|
71 |
* along with this program; if not, write to the Free Software
|
72 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
|
73 |
*
|
74 |
* For more information, contact:
|
75 |
*
|
76 |
* Generalitat Valenciana
|
77 |
* Conselleria d'Infraestructures i Transport
|
78 |
* Av. Blasco Ib??ez, 50
|
79 |
* 46010 VALENCIA
|
80 |
* SPAIN
|
81 |
*
|
82 |
* +34 963862235
|
83 |
* gvsig@gva.es
|
84 |
* www.gvsig.gva.es
|
85 |
*
|
86 |
* or
|
87 |
*
|
88 |
* IVER T.I. S.A
|
89 |
* Salamanca 50
|
90 |
* 46005 Valencia
|
91 |
* Spain
|
92 |
*
|
93 |
* +34 963163400
|
94 |
* dac@iver.es
|
95 |
*/
|
96 |
|
97 |
/**
|
98 |
* <p>Panel that provides tools to apply a filter to the values of a feature.</p>
|
99 |
* <p>Improves the functionality of {@link FilterQueryJPanel FilterQueryJPanel}.</p>
|
100 |
*
|
101 |
* @see FilterQueryJPanel
|
102 |
*
|
103 |
* @author Pablo Piqueras Bartolom? (p_queras@hotmail.com)
|
104 |
*/
|
105 |
public class WFSFilterPanel extends FilterQueryJPanel implements IWFSPanel { |
106 |
private static final long serialVersionUID = -6041218260822015810L; |
107 |
private static final Logger LOG = LoggerFactory.getLogger(WFSFilterPanel.class); |
108 |
|
109 |
private static Logger logger = LoggerFactory.getLogger(WFSFilterPanel.class); |
110 |
private ExpressionDataSource model = null; |
111 |
private FieldsTreeTableModel fieldsTreeTableModel;
|
112 |
private boolean panelAsATabForWFSLayersLoad; |
113 |
private TreePath currentPath; |
114 |
private Map<String, Map<String, String>> allFieldsAndValuesKnownOfCurrentLayer; // This will have all values (not repeated) known of all fields (not repeated) |
115 |
|
116 |
private DataStore dataStore = null; |
117 |
|
118 |
///// GUI METHODS ////
|
119 |
|
120 |
/**
|
121 |
* This method initializes
|
122 |
*
|
123 |
* @param parent A reference to the parent container component of this component
|
124 |
*/
|
125 |
public WFSFilterPanel() {
|
126 |
super();
|
127 |
currentPath = null;
|
128 |
allFieldsAndValuesKnownOfCurrentLayer = new HashMap<String, Map<String, String>>(); // Initial capacity = 0 |
129 |
|
130 |
// At beginning, the JList is disabled (and its set a particular color for user could knew it)
|
131 |
super.getValuesJList().setEnabled(false); |
132 |
//getValuesJList().setBackground(new Color(220, 220, 220));
|
133 |
|
134 |
//The validation option is disabled by default
|
135 |
this.getValidateFilterExpressionJCheckBox().setSelected(false); |
136 |
} |
137 |
|
138 |
/*
|
139 |
* (non-Javadoc)
|
140 |
* @see org.gvsig.gui.beans.filterPanel.AbstractFilterQueryJPanel#initialize()
|
141 |
*/
|
142 |
protected void initialize() { |
143 |
setLabel(PluginServices.getText(this, "filter")); |
144 |
setLabelGroup(PluginServices.getText(this, "wfs")); |
145 |
super.initialize();
|
146 |
this.resizeHeight(380); |
147 |
|
148 |
defaultTreeModel = (DefaultTreeModel)fieldsJTree.getModel();
|
149 |
|
150 |
this.addNewListeners();
|
151 |
panelAsATabForWFSLayersLoad = true;
|
152 |
getValidateFilterExpressionJCheckBox().setSelected(true);
|
153 |
|
154 |
getValuesJLabel().setToolTipText(Messages.getText("values_of_the_selected_field_explanation"));
|
155 |
getFieldsJLabel().setToolTipText(Messages.getText("fields_of_the_selected_feature_explanation"));
|
156 |
} |
157 |
|
158 |
/**
|
159 |
* Adds some more listener to the components of the panel
|
160 |
*/
|
161 |
private void addNewListeners() { |
162 |
// Enable "Apply" button when user changes the filter query
|
163 |
txtExpression.getDocument().addDocumentListener(new DocumentListener() { |
164 |
/*
|
165 |
* (non-Javadoc)
|
166 |
* @see javax.swing.event.DocumentListener#changedUpdate(javax.swing.event.DocumentEvent)
|
167 |
*/
|
168 |
public void changedUpdate(DocumentEvent e) { |
169 |
} |
170 |
|
171 |
/*
|
172 |
* (non-Javadoc)
|
173 |
* @see javax.swing.event.DocumentListener#insertUpdate(javax.swing.event.DocumentEvent)
|
174 |
*/
|
175 |
public void insertUpdate(DocumentEvent e) { |
176 |
if (!panelAsATabForWFSLayersLoad) {
|
177 |
IPanelGroup panelGroup = getPanelGroup(); |
178 |
|
179 |
if (panelGroup == null) |
180 |
return;
|
181 |
|
182 |
((WFSParamsPanel)panelGroup).setApplicable(true);
|
183 |
} |
184 |
} |
185 |
|
186 |
/*
|
187 |
* (non-Javadoc)
|
188 |
* @see javax.swing.event.DocumentListener#removeUpdate(javax.swing.event.DocumentEvent)
|
189 |
*/
|
190 |
public void removeUpdate(DocumentEvent e) { |
191 |
if (!panelAsATabForWFSLayersLoad) {
|
192 |
IPanelGroup panelGroup = getPanelGroup(); |
193 |
|
194 |
if (panelGroup == null) |
195 |
return;
|
196 |
|
197 |
((WFSParamsPanel)panelGroup).setApplicable(true);
|
198 |
} |
199 |
} |
200 |
}); |
201 |
|
202 |
// Listener for "fieldsJTree"
|
203 |
getFieldsJTree().addMouseListener(new MouseAdapter() { |
204 |
/*
|
205 |
* (non-Javadoc)
|
206 |
* @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
|
207 |
*/
|
208 |
public void mouseClicked(MouseEvent e) { |
209 |
int row = fieldsJTree.getRowForLocation(e.getX(), e.getY());
|
210 |
TreePath treePath = fieldsJTree.getPathForLocation(e.getX(), e.getY());
|
211 |
|
212 |
if (row > -1) { |
213 |
switch (e.getClickCount()) {
|
214 |
case 2: |
215 |
putSymbolOfSelectedByMouseBranch(treePath); |
216 |
break;
|
217 |
} |
218 |
} |
219 |
} |
220 |
}); |
221 |
|
222 |
// Listener for "valuesJList"
|
223 |
getValuesJList().addMouseListener(new MouseAdapter() { |
224 |
/*
|
225 |
* (non-Javadoc)
|
226 |
* @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
|
227 |
*/
|
228 |
public void mouseClicked(MouseEvent e) { |
229 |
int index = getValuesJList().getSelectedIndex();
|
230 |
|
231 |
// Avoids exception when no value is in the list
|
232 |
if (index == -1) |
233 |
return;
|
234 |
|
235 |
if (e.getClickCount() == 2){ |
236 |
String valor = valuesListModel.getElementAt(index).toString();
|
237 |
|
238 |
// If value is an string -> set it between apostrophes
|
239 |
if (getNodeOfCurrentPath().getDataType().getType() == DataTypes.STRING) {
|
240 |
putSymbol("'" + valor + "'"); |
241 |
} |
242 |
else {
|
243 |
putSymbol(valor); |
244 |
} |
245 |
} |
246 |
} |
247 |
}); |
248 |
|
249 |
// Listener for a branch of the tree selection
|
250 |
getFieldsJTree().addTreeSelectionListener(new TreeSelectionListener() { |
251 |
/*
|
252 |
* (non-Javadoc)
|
253 |
* @see javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event.TreeSelectionEvent)
|
254 |
*/
|
255 |
public void valueChanged(TreeSelectionEvent e) { |
256 |
if (dataStore != null){ |
257 |
currentPath = e.getPath(); |
258 |
fillValuesByPath(currentPath); |
259 |
} |
260 |
} |
261 |
}); |
262 |
|
263 |
// Listener: when a user writes something on the textarea -> set it's foreground color to black
|
264 |
getTxtExpression().getDocument().addDocumentListener(new DocumentListener() { |
265 |
/*
|
266 |
* (non-Javadoc)
|
267 |
* @see javax.swing.event.DocumentListener#changedUpdate(javax.swing.event.DocumentEvent)
|
268 |
*/
|
269 |
public void changedUpdate(DocumentEvent e) { |
270 |
} |
271 |
|
272 |
/*
|
273 |
* (non-Javadoc)
|
274 |
* @see javax.swing.event.DocumentListener#insertUpdate(javax.swing.event.DocumentEvent)
|
275 |
*/
|
276 |
public void insertUpdate(DocumentEvent e) { |
277 |
getTxtExpression().setForeground(Color.BLACK);
|
278 |
} |
279 |
|
280 |
/*
|
281 |
* (non-Javadoc)
|
282 |
* @see javax.swing.event.DocumentListener#removeUpdate(javax.swing.event.DocumentEvent)
|
283 |
*/
|
284 |
public void removeUpdate(DocumentEvent e) { |
285 |
getTxtExpression().setForeground(Color.BLACK);
|
286 |
} |
287 |
}); |
288 |
} |
289 |
|
290 |
/**
|
291 |
* Gets the element that the 'currentPath' field aims
|
292 |
*
|
293 |
* @return An XMLElement
|
294 |
*/
|
295 |
private WFSFeatureField getNodeOfCurrentPath() {
|
296 |
|
297 |
if (currentPath != null) { |
298 |
Object node = currentPath.getLastPathComponent();
|
299 |
|
300 |
if ((node != null) && (node instanceof WFSFeatureField)) { |
301 |
return (WFSFeatureField) node;
|
302 |
} |
303 |
} |
304 |
|
305 |
return null; |
306 |
} |
307 |
|
308 |
/**
|
309 |
* Puts the symbol of selected branch
|
310 |
*
|
311 |
* @param mouseEvent A MouseEvent with information of the selected branch
|
312 |
*/
|
313 |
public void putSymbolOfSelectedByMouseBranch(TreePath treePath) { |
314 |
// Sets the node selected
|
315 |
if (treePath != null) { |
316 |
putSymbol("\"" + this.getPathOfLeafWithoutRoot(treePath.getLastPathComponent().toString()) + "\""); |
317 |
} |
318 |
} |
319 |
|
320 |
/**
|
321 |
* This method returns the path without the root, of a node of a tree
|
322 |
* Each node is separated from its parent with the symbol "/"
|
323 |
*
|
324 |
* @param node A leaf node
|
325 |
* @return An string with the path
|
326 |
*/
|
327 |
private String getPathOfLeafWithoutRoot(Object node) { |
328 |
String path = ""; |
329 |
|
330 |
if ((node != null) && (node instanceof IXSElementDeclaration)) { |
331 |
IXSElementDeclaration element = (IXSElementDeclaration) node; |
332 |
IXSElementDeclaration parent = element.getParentElement(); |
333 |
path = element.getNodeName(); |
334 |
|
335 |
while (parent.getParentElement() != null){ |
336 |
path = parent.getNodeName() + "/" + path;
|
337 |
parent = parent.getParentElement(); |
338 |
} |
339 |
}else if (node instanceof String){ |
340 |
path = node.toString(); |
341 |
} |
342 |
|
343 |
return path;
|
344 |
} |
345 |
|
346 |
/**
|
347 |
* Gets the value of the inner attribute: 'panelAsATabForWFSLayersLoad'
|
348 |
*
|
349 |
* @return A boolean value
|
350 |
*/
|
351 |
public boolean getWFSFilterPanelIsAsTabForWFSLayersLoad() { |
352 |
return this.panelAsATabForWFSLayersLoad; |
353 |
} |
354 |
|
355 |
/**
|
356 |
* Refresh all information about fields
|
357 |
*
|
358 |
* @param feature a feature with fields
|
359 |
*/
|
360 |
public void refresh(WFSSelectedFeature feature) { |
361 |
setFields(feature); |
362 |
} |
363 |
|
364 |
/**
|
365 |
* Gets the query that will be send to the server
|
366 |
* @return SQL query (just the where part)
|
367 |
*/
|
368 |
public String getQuery(){ |
369 |
String writtenQuery = txtExpression.getText().trim();
|
370 |
|
371 |
// Validate expression
|
372 |
if (!this.validateExpression(writtenQuery)) { |
373 |
getTxtExpression().setForeground(Color.red);
|
374 |
return null; |
375 |
} |
376 |
else {
|
377 |
logger.debug("Codified WFS filter query: " + writtenQuery);
|
378 |
|
379 |
if (writtenQuery.trim().length() == 0){ |
380 |
return null; |
381 |
} |
382 |
// Codify expression (only if the validation has been successful)
|
383 |
return formatResutl(writtenQuery); // Ignores the spaces at beginning and end of the chain of characters |
384 |
} |
385 |
} |
386 |
|
387 |
/**
|
388 |
* Gets the filter expression from the user interface
|
389 |
*/
|
390 |
public String getFilterExpressionFromInterface() { |
391 |
return getTxtExpression().getText();
|
392 |
} |
393 |
|
394 |
/**
|
395 |
* Writes the filter expression into the user interface
|
396 |
* @param filterExpression An string
|
397 |
*/
|
398 |
public void setFilterExpressionIntoInterface(String filterExpression){ |
399 |
getTxtExpression().setText(filterExpression); |
400 |
} |
401 |
|
402 |
/**
|
403 |
* Removes text in the JTextArea that has the filter subconsultation
|
404 |
*/
|
405 |
public void removeFilterExpression() { |
406 |
getTxtExpression().setText("");
|
407 |
} |
408 |
|
409 |
private String formatResutl(String query) { |
410 |
if ((query == null) || (query.equals(""))){ |
411 |
return null; |
412 |
} |
413 |
InputStream is = new ByteArrayInputStream(query.getBytes()); |
414 |
ZqlParser parser = new ZqlParser();
|
415 |
parser.initParser(is); |
416 |
ZExp exp; |
417 |
try {
|
418 |
exp = parser.readExpression(); |
419 |
return exp.toString();
|
420 |
} catch (Zql.ParseException e) {
|
421 |
LOG.error("Formatting the filter request", e);
|
422 |
JOptionPane.showMessageDialog(null, PluginServices.getText(null, "filter_with_an_incorrect_format"), PluginServices.getText(null, "error_validating_filter_query"), JOptionPane.ERROR_MESSAGE); |
423 |
} |
424 |
return query;
|
425 |
} |
426 |
|
427 |
/**
|
428 |
* Checks the filter expression if it's correct
|
429 |
*
|
430 |
* @param query The query expression to analyze
|
431 |
* @return True if it's valid or false if not
|
432 |
*/
|
433 |
private boolean validateExpression(String query) { |
434 |
try {
|
435 |
// If it's needed to validate the query
|
436 |
if (getValidateFilterExpressionJCheckBox().isSelected()) {
|
437 |
// If it's an empty query -> ok
|
438 |
if (query.trim().length() == 0) |
439 |
return true; |
440 |
|
441 |
// Replace all Date(dd-mmm-yyyy) format to ddd-mmm-yyyy (characters will replaced to spaces)
|
442 |
int index = 0; |
443 |
String query_copy = new String(query); |
444 |
while ((index = query_copy.indexOf("Date(", index)) != -1) { |
445 |
if (index > 0) { |
446 |
if ((query_copy.charAt(index-1) != ' ') && (query_copy.charAt(index-1) != '(')) |
447 |
break;
|
448 |
} |
449 |
|
450 |
if (((index + 16) < query_copy.length()) && (query_copy.charAt(index + 16) == ')')) { // +17 is the length of Date(dd-mmm-yyyy) |
451 |
if ((index + 17) < query_copy.length()) { |
452 |
query_copy = query_copy.substring(0, index) + " " + query_copy.substring(index+6, index+16) + " " + query_copy.substring(index+17); |
453 |
} |
454 |
else {
|
455 |
query_copy = query_copy.substring(0, index) + " " + query_copy.substring(index+6, index+16); |
456 |
} |
457 |
} |
458 |
} |
459 |
|
460 |
SQLQueryValidation sQLQueryValidation = new SQLQueryValidation(formatSQLQuery(query_copy), true); |
461 |
|
462 |
// Tries to validate the query, and if fails shows a message
|
463 |
if (!sQLQueryValidation.validateQuery()) {
|
464 |
JOptionPane.showMessageDialog(null, PluginServices.getText(null, "filter_with_an_incorrect_format") + ": " + PluginServices.getText(null, "finded") + " " + sQLQueryValidation.getTokenThatProducedTheSyntacticError() + " " + PluginServices.getText(null, "in") + " " + sQLQueryValidation.getErrorPositionAsMessage() + ".", PluginServices.getText(null, "error_validating_filter_query"), JOptionPane.ERROR_MESSAGE); |
465 |
return false; |
466 |
} |
467 |
else {
|
468 |
// Analyzes tokens in query
|
469 |
StringTokenizer tokens = new StringTokenizer(query, " "); |
470 |
String token, token_aux;
|
471 |
boolean finish = false; |
472 |
|
473 |
// If there is a field or a value with spaces, (and then it's on differents tokens) -> unify them
|
474 |
while (tokens.hasMoreTokens()) {
|
475 |
token = tokens.nextToken().trim(); |
476 |
|
477 |
if (token.charAt(0) == '\'') { |
478 |
if (token.charAt(token.length() -1) != '\'') { |
479 |
while (!finish) {
|
480 |
if (!tokens.hasMoreTokens()) {
|
481 |
JOptionPane.showMessageDialog(null, PluginServices.getText(null, "filter_with_an_incorrect_format") + ": " + PluginServices.getText(null, "the_token") + " " + token + " " + PluginServices.getText(null, "has_bad_format"), PluginServices.getText(null, "error_validating_filter_query"), JOptionPane.ERROR_MESSAGE); |
482 |
return false; |
483 |
} |
484 |
else {
|
485 |
token_aux = tokens.nextToken().trim(); |
486 |
token += " " + token_aux;
|
487 |
|
488 |
if (token_aux.charAt(token_aux.length() -1) == '\'') |
489 |
finish = true;
|
490 |
} |
491 |
} |
492 |
|
493 |
finish = false;
|
494 |
} |
495 |
} |
496 |
|
497 |
if (token.charAt(0) == '\"') { |
498 |
if (token.charAt(token.length() -1) != '\"') { |
499 |
while (!finish) {
|
500 |
if (!tokens.hasMoreTokens()) {
|
501 |
JOptionPane.showMessageDialog(null, PluginServices.getText(null, "filter_with_an_incorrect_format") + ": " + PluginServices.getText(null, "the_token") + " " + token + " " + PluginServices.getText(null, "has_bad_format"), PluginServices.getText(null, "error_validating_filter_query"), JOptionPane.ERROR_MESSAGE); |
502 |
return false; |
503 |
} |
504 |
else {
|
505 |
token_aux = tokens.nextToken().trim(); |
506 |
token += " " + token_aux;
|
507 |
|
508 |
if (token_aux.charAt(token_aux.length() -1) == '\"') |
509 |
finish = true;
|
510 |
} |
511 |
} |
512 |
|
513 |
finish = false;
|
514 |
} |
515 |
} |
516 |
|
517 |
// Tries to find an invalid token
|
518 |
if (token.length() > 0) { |
519 |
// Validates if a supposed field exists
|
520 |
if ( (token.length() > 2) && (token.charAt(0) == '\"') && (token.charAt(token.length()-1) == '\"') ) { |
521 |
if (! this.isAField(token.substring(1, token.length()-1))) { |
522 |
JOptionPane.showMessageDialog(null, PluginServices.getText(null, "filter_with_an_incorrect_format") + ": " + PluginServices.getText(null, "the_token") + " " + token + " " + PluginServices.getText(null, "isnt_a_field_of_layer"), PluginServices.getText(null, "error_validating_filter_query"), JOptionPane.ERROR_MESSAGE); |
523 |
return false; |
524 |
} |
525 |
} |
526 |
else {
|
527 |
// If it's an string -> ignore
|
528 |
if (! ((token.charAt(0) == token.charAt(token.length() - 1)) && (token.charAt(0) == '\''))) { |
529 |
|
530 |
// If it's a date -> ignore
|
531 |
int returnValue = validateDate(token);
|
532 |
|
533 |
if (returnValue == 1) { |
534 |
JOptionPane.showMessageDialog(null, PluginServices.getText(null, "filter_with_an_incorrect_format") + ": " + PluginServices.getText(null, "incorrect_format_on_date") + " " + token.substring(5, 16) + " .", PluginServices.getText(null, "error_validating_filter_query"), JOptionPane.ERROR_MESSAGE); |
535 |
return false; |
536 |
} |
537 |
|
538 |
if (returnValue == 2) { |
539 |
// Else -> Checks if the current token is a valid number or symbol
|
540 |
if ((! StringNumberUtilities.isRealNumberWithIntegerExponent(token)) && (! this.isAnOperatorNameOrSymbol(token, getAllOperatorSymbols()))) { |
541 |
JOptionPane.showMessageDialog(null, PluginServices.getText(null, "filter_with_an_incorrect_format") + ": " + PluginServices.getText(null, "not_valid_token") + ": " + token, PluginServices.getText(null, "error_validating_filter_query"), JOptionPane.ERROR_MESSAGE); |
542 |
return false; |
543 |
} |
544 |
} |
545 |
} |
546 |
} |
547 |
} |
548 |
} |
549 |
|
550 |
// If has validate all tokens -> query validated
|
551 |
return true; |
552 |
} |
553 |
} |
554 |
else
|
555 |
return true; // No validation done because user selected that option |
556 |
} |
557 |
catch (Exception e) { |
558 |
NotificationManager.showMessageError(PluginServices.getText(null, "filter_with_an_incorrect_format") + ".", e); |
559 |
return true; // No validation done because user selected that option |
560 |
} |
561 |
} |
562 |
|
563 |
/**
|
564 |
* <p>Formats a query removing non English symbols that can produce the SQL validator could invalidate it.</p>
|
565 |
*
|
566 |
* @param an SQL query
|
567 |
* @return the SQL query without non English symbols
|
568 |
*/
|
569 |
private String formatSQLQuery(String token) { |
570 |
return token = token.replace("?", "n").replace("?", "c").replace("?", "a"). |
571 |
replace("?", "e").replace("?", "i").replace("?", "o").replace("?", "u").replace("?", "a"). |
572 |
replace("?", "e").replace("?", "i").replace("?", "o").replace("?", "u").replace("?", "a"). |
573 |
replace("?", "e").replace("?", "i").replace("?", "o").replace("?", "u").replace("?", "a"). |
574 |
replace("?", "e").replace("?", "i").replace("?", "o").replace("?", "u"); |
575 |
} |
576 |
|
577 |
/**
|
578 |
* Returns true if there is a field with the same name as 'text'
|
579 |
*
|
580 |
* @param text An string
|
581 |
* @return A boolean value
|
582 |
*/
|
583 |
private boolean isAField(String text) { |
584 |
return this.allFieldsAndValuesKnownOfCurrentLayer.containsKey(text); |
585 |
} |
586 |
|
587 |
/**
|
588 |
* Validates if a text has a correct date format as Date(dd-mmm-yyyy) (Ex. Date(03-feb-2004) )
|
589 |
*
|
590 |
* @param text date to validate
|
591 |
* @return 0 -> if has a date format; 1 -> if it's a date that has a but format; 2 -> if it isn't a date
|
592 |
*/
|
593 |
private int validateDate(String text) { |
594 |
// If it's a date -> check if format is correct (Ex. Date(01-feb-2004) )
|
595 |
if ( ((text.length() == 17) && (text.startsWith("Date(")) && (text.endsWith(")"))) && (text.charAt(7) == '-') && (text.charAt(11) == '-') ) { |
596 |
if ( (StringNumberUtilities.isNaturalNumber(text.substring(5, 7))) && (StringNumberUtilities.isNaturalNumber(text.substring(12, 16))) ) { |
597 |
try {
|
598 |
// If can parse the date -> date with a correct format
|
599 |
DateFormat.getDateInstance().parse(text.substring(5, 16)); |
600 |
return 0; |
601 |
} catch (ParseException e) { |
602 |
// If can't parse the date -> date with an incorrect format
|
603 |
NotificationManager.addError(e); |
604 |
return 1; |
605 |
} |
606 |
} |
607 |
else {
|
608 |
return 1; |
609 |
} |
610 |
} |
611 |
|
612 |
return 2; |
613 |
} |
614 |
|
615 |
/**
|
616 |
* Returns true if there is the 'text' is a symbol or a operator name
|
617 |
*
|
618 |
* @param text An string
|
619 |
* @return A boolean value
|
620 |
*/
|
621 |
private boolean isAnOperatorNameOrSymbol(String text, Set<String> operatorNamesAndSymbols) { |
622 |
return operatorNamesAndSymbols.contains(text);
|
623 |
} |
624 |
|
625 |
/**
|
626 |
* Sets the model with the fields and values of the feature selected.
|
627 |
*
|
628 |
* @param eds data source with the model of the feature selected
|
629 |
*/
|
630 |
public void setModel(ExpressionDataSource eds) { |
631 |
// try {
|
632 |
model = eds; |
633 |
// model.start();
|
634 |
// } catch (ReadDriverException e1) {
|
635 |
// NotificationManager.addError(e1);
|
636 |
// }
|
637 |
|
638 |
try {
|
639 |
int numberOfFields = model.getFieldCount();
|
640 |
|
641 |
if (numberOfFields > 0) { |
642 |
Vector<Object> fields = new Vector<Object>(0, 1); |
643 |
int j = 0; |
644 |
|
645 |
for (int i = 0; i < numberOfFields; i++) { |
646 |
Object field = model.getFieldName(i);
|
647 |
|
648 |
if (field != null) { |
649 |
fields.add(field); |
650 |
|
651 |
String completeFieldPath = this.getPathOfLeafWithoutRoot(field); |
652 |
|
653 |
if (! allFieldsAndValuesKnownOfCurrentLayer.containsKey(completeFieldPath) ) {
|
654 |
allFieldsAndValuesKnownOfCurrentLayer.put(completeFieldPath, new HashMap<String, String>()); |
655 |
} |
656 |
|
657 |
j++; |
658 |
} |
659 |
} |
660 |
|
661 |
fieldsTreeTableModel = new FieldsTreeTableModel(fields.toArray());
|
662 |
} |
663 |
} catch (FilterException e) {
|
664 |
NotificationManager.addError(e); |
665 |
} |
666 |
} |
667 |
|
668 |
/**
|
669 |
* Adds the fields of the feature.
|
670 |
*
|
671 |
* @param feature A Layer node with fields information
|
672 |
*/
|
673 |
private boolean setFields(WFSSelectedFeature feature) { |
674 |
|
675 |
this.resetFieldsAndValuesData();
|
676 |
|
677 |
int numberOfFields = feature.getWFSFeature().getFieldSize();
|
678 |
|
679 |
if (numberOfFields > 0) { |
680 |
Vector<WFSFeatureField> fieldBranches = new Vector<WFSFeatureField>(0, 1); |
681 |
|
682 |
for (int i=0 ; i<numberOfFields ; i++) { |
683 |
WFSFeatureField featureField = feature.getWFSFeature().getFieldAt(i); |
684 |
if (!featureField.isGeometry()) {
|
685 |
fieldBranches.add(featureField); |
686 |
} |
687 |
} |
688 |
|
689 |
|
690 |
if (fieldBranches.size() > 0) { |
691 |
Object obj = fieldBranches.get(0); |
692 |
|
693 |
fieldsTreeTableModel = new FieldsTreeTableModel(feature.getWFSFeature(), false); |
694 |
fieldsJTree.setModel(new FieldsTreeTableModel(feature.getWFSFeature(), false)); |
695 |
|
696 |
// Stores the name of all leafs (fields) of treeTableModel
|
697 |
Object root = fieldsTreeTableModel.getRoot();
|
698 |
|
699 |
if (root != null) { |
700 |
Vector<Object> fieldsNames = fieldsTreeTableModel.getLeafsFromNodeBranch(root); |
701 |
|
702 |
for (Object field : fieldsNames) { |
703 |
// Avoid errors
|
704 |
if ( (! (field instanceof WFSFeatureField)) || (field == null) ) continue; |
705 |
|
706 |
// Don't load a geometry field
|
707 |
if (((WFSFeatureField)field).isGeometry()){
|
708 |
continue;
|
709 |
} |
710 |
|
711 |
|
712 |
String completeFieldPath = this.getPathOfLeafWithoutRoot(field); |
713 |
|
714 |
if (! allFieldsAndValuesKnownOfCurrentLayer.containsKey(completeFieldPath) ) {
|
715 |
allFieldsAndValuesKnownOfCurrentLayer.put(completeFieldPath, new HashMap<String, String>()); |
716 |
} |
717 |
} |
718 |
} |
719 |
} |
720 |
} |
721 |
|
722 |
return true; |
723 |
} |
724 |
|
725 |
/**
|
726 |
* Resets the data of fields and their values of the current layer feature, and removes the branches of <code>fieldsJTree</code>.
|
727 |
*/
|
728 |
private void resetFieldsAndValuesData() { |
729 |
fieldsJTree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode())); |
730 |
txtExpression.setText("");
|
731 |
((DefaultListModel)valuesJList.getModel()).removeAllElements();
|
732 |
} |
733 |
|
734 |
/**
|
735 |
* Fills list with the values of selected field.
|
736 |
*
|
737 |
* @param treePath A path in the tree
|
738 |
*/
|
739 |
private void fillValuesByPath(TreePath treePath) { |
740 |
// Duplicates are removed
|
741 |
TreeSet<Object> fieldValueSet = new TreeSet<Object>(new Comparator<Object>() { |
742 |
public int compare(Object o1, Object o2) { |
743 |
if ((o1 != null) && (o2 != null)) { |
744 |
return o1.toString().compareTo(o2.toString());
|
745 |
} |
746 |
return 0; |
747 |
} |
748 |
}); // For ordernation
|
749 |
|
750 |
// Remove the previous items
|
751 |
valuesListModel.clear(); |
752 |
|
753 |
try {
|
754 |
WFSFeatureField wfsFeatureField = ((WFSFeatureField)treePath.getLastPathComponent()); |
755 |
|
756 |
if (wfsFeatureField == null){ |
757 |
return;
|
758 |
} |
759 |
|
760 |
FeatureStore featureStore = (FeatureStore)dataStore; |
761 |
FeatureAttributeDescriptor featureAttributeDescriptor = featureStore.getDefaultFeatureType().getAttributeDescriptor(wfsFeatureField.getName()); |
762 |
|
763 |
if (featureAttributeDescriptor == null){ |
764 |
return;
|
765 |
} |
766 |
|
767 |
if(!wfsFeatureField.isComplex()){
|
768 |
DisposableIterator disposableIterator = featureStore.getFeatureSet().iterator(); |
769 |
while (disposableIterator.hasNext()){
|
770 |
Feature feature = (Feature)disposableIterator.next(); |
771 |
Object obj = feature.get(featureAttributeDescriptor.getIndex());
|
772 |
if (!fieldValueSet.contains(obj)){
|
773 |
fieldValueSet.add(obj); |
774 |
} |
775 |
} |
776 |
|
777 |
Iterator it = fieldValueSet.iterator();
|
778 |
while (it.hasNext()) {
|
779 |
String text = it.next().toString();
|
780 |
valuesListModel.addElement(text); |
781 |
} |
782 |
} |
783 |
|
784 |
this.getValuesJList().setEnabled(valuesListModel.getSize() > 0); |
785 |
|
786 |
} catch (Exception e) { |
787 |
NotificationManager.addError(e); |
788 |
} |
789 |
} |
790 |
|
791 |
/**
|
792 |
* Sets all fields and values known about the current layer
|
793 |
*
|
794 |
* @param _allFieldsAndValuesKnownOfCurrentLayer A Map object
|
795 |
*/
|
796 |
public void setAllFieldsAndValuesKnownOfCurrentLayer(Map<String, Map<String, String>> _allFieldsAndValuesKnownOfCurrentLayer) { |
797 |
if (_allFieldsAndValuesKnownOfCurrentLayer == null) |
798 |
this.allFieldsAndValuesKnownOfCurrentLayer = new HashMap<String, Map<String, String>>(); |
799 |
else
|
800 |
this.allFieldsAndValuesKnownOfCurrentLayer = _allFieldsAndValuesKnownOfCurrentLayer;
|
801 |
} |
802 |
|
803 |
/**
|
804 |
* Gets all fields and values known about the current layer
|
805 |
*
|
806 |
* @return _allFieldsAndValuesKnownOfCurrentLayer A Map object
|
807 |
*/
|
808 |
public Map<String, Map<String, String>> getAllFieldsAndValuesKnownOfCurrentLayer() { |
809 |
return allFieldsAndValuesKnownOfCurrentLayer;
|
810 |
} |
811 |
|
812 |
/**
|
813 |
* @param layer
|
814 |
*/
|
815 |
public void setDataStore(DataStore dataStore) { |
816 |
this.dataStore = dataStore;
|
817 |
|
818 |
} |
819 |
} |