Statistics
| Revision:

root / tags / v2_0_0_Build_2051 / extensions / extWFS2 / src / org / gvsig / wfs / gui / panels / WFSFilterPanel.java @ 38727

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
}