Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extWFS2 / src / com / iver / cit / gvsig / gui / panels / WFSFilterPanel.java @ 9343

History | View | Annotate | Download (38.5 KB)

1
package com.iver.cit.gvsig.gui.panels;
2

    
3
import java.awt.Color;
4
import java.awt.event.MouseAdapter;
5
import java.awt.event.MouseEvent;
6
import java.io.UnsupportedEncodingException;
7
import java.net.URLEncoder;
8
import java.text.NumberFormat;
9
import java.text.ParseException;
10
import java.util.ArrayList;
11
import java.util.Comparator;
12
import java.util.HashMap;
13
import java.util.Iterator;
14
import java.util.Map;
15
import java.util.Set;
16
import java.util.TreeSet;
17
import java.util.Vector;
18
import java.util.regex.Matcher;
19
import java.util.regex.Pattern;
20

    
21
import javax.swing.DefaultListModel;
22
import javax.swing.JLabel;
23
import javax.swing.JOptionPane;
24
import javax.swing.event.DocumentEvent;
25
import javax.swing.event.DocumentListener;
26
import javax.swing.event.TreeSelectionEvent;
27
import javax.swing.event.TreeSelectionListener;
28
import javax.swing.tree.DefaultMutableTreeNode;
29
import javax.swing.tree.DefaultTreeModel;
30
import javax.swing.tree.TreePath;
31

    
32
import org.apache.log4j.Logger;
33
import org.gvsig.gui.beans.Messages;
34
import org.gvsig.gui.beans.filterPanel.filterQueryPanel.FilterQueryJPanel;
35
import org.gvsig.remoteClient.gml.schemas.IXMLType;
36
import org.gvsig.remoteClient.gml.schemas.XMLElement;
37

    
38
import com.hardcode.gdbms.engine.data.driver.DriverException;
39
import com.hardcode.gdbms.engine.instruction.IncompatibleTypesException;
40
import com.hardcode.gdbms.engine.values.BooleanValue;
41
import com.hardcode.gdbms.engine.values.ComplexValue;
42
import com.hardcode.gdbms.engine.values.NullValue;
43
import com.hardcode.gdbms.engine.values.Value;
44
import com.iver.andami.PluginServices;
45
import com.iver.andami.messages.NotificationManager;
46
import com.iver.andami.ui.mdiManager.IWindow;
47
import com.iver.andami.ui.mdiManager.IWindowListener;
48
import com.iver.andami.ui.mdiManager.WindowInfo;
49
import com.iver.cit.gvsig.ProjectExtension;
50
import com.iver.cit.gvsig.fmap.edition.EditableAdapter;
51
import com.iver.cit.gvsig.fmap.edition.VectorialEditableAdapter;
52
import com.iver.cit.gvsig.fmap.layers.FLayer;
53
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
54
import com.iver.cit.gvsig.fmap.layers.ReadableVectorial;
55
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
56
import com.iver.cit.gvsig.fmap.layers.WFSLayerNode;
57
import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData;
58
import com.iver.cit.gvsig.gui.filter.ExpressionDataSource;
59
import com.iver.cit.gvsig.gui.filter.ExpressionListener;
60
import com.iver.cit.gvsig.gui.filter.FilterException;
61
import com.iver.cit.gvsig.gui.panels.attributesTree.AttributesTreeTableModel;
62
import com.iver.cit.gvsig.gui.panels.sqlFormat.SQLExpressionFormatForFilterGUI;
63
import com.iver.cit.gvsig.project.ProjectFactory;
64
import com.iver.cit.gvsig.project.documents.table.ProjectTable;
65
import com.iver.cit.gvsig.project.documents.table.ProjectTableFactory;
66
import com.iver.cit.gvsig.project.documents.table.gui.Table;
67
import com.iver.cit.gvsig.project.documents.view.gui.View;
68
import com.iver.utiles.DefaultCharSet;
69
import com.iver.utiles.StringUtilities;
70
import com.iver.utiles.exceptionHandling.ExceptionHandlingSupport;
71
import com.iver.utiles.exceptionHandling.ExceptionListener;
72

    
73

    
74
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
75
 *
76
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
77
 *
78
 * This program is free software; you can redistribute it and/or
79
 * modify it under the terms of the GNU General Public License
80
 * as published by the Free Software Foundation; either version 2
81
 * of the License, or (at your option) any later version.
82
 *
83
 * This program is distributed in the hope that it will be useful,
84
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
85
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
86
 * GNU General Public License for more details.
87
 *
88
 * You should have received a copy of the GNU General Public License
89
 * along with this program; if not, write to the Free Software
90
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
91
 *
92
 * For more information, contact:
93
 *
94
 *  Generalitat Valenciana
95
 *   Conselleria d'Infraestructures i Transport
96
 *   Av. Blasco Ib??ez, 50
97
 *   46010 VALENCIA
98
 *   SPAIN
99
 *
100
 *      +34 963862235
101
 *   gvsig@gva.es
102
 *      www.gvsig.gva.es
103
 *
104
 *    or
105
 *
106
 *   IVER T.I. S.A
107
 *   Salamanca 50
108
 *   46005 Valencia
109
 *   Spain
110
 *
111
 *   +34 963163400
112
 *   dac@iver.es
113
 */
114

    
115
/**
116
 * This will be the tab for add a filter to a WFS query.
117
 * This class gets the graphical interface from FilterQueryJPanel and add logic.
118
 * 
119
 * @author Pablo Piqueras Bartolom? (p_queras@hotmail.com)
120
 */
121
public class WFSFilterPanel extends FilterQueryJPanel implements IWindow, IWindowListener {
122
        private static Logger logger = Logger.getLogger(Table.class.getName());
123
        private WFSParamsPanel parent = null;
124
        private ArrayList expressionListeners = new ArrayList();
125
        private ExpressionDataSource model = null;
126
        private NumberFormat nf = NumberFormat.getNumberInstance();
127
        private ExceptionHandlingSupport exceptionHandlingSupport = new ExceptionHandlingSupport();
128
        private AttributesTreeTableModel attributesTreeTableModel;
129
        private boolean panelAsATabForWFSLayersLoad;
130
        private TreePath currentPath;
131
        private String featureName;
132
        private Map allFieldsAndValuesKnownOfCurrentLayer; // This will have all values (not repeated) known of all fields (not repeated)
133
        
134
        ///// GUI METHODS ////
135
        
136
        /**
137
         * This method initializes
138
         * 
139
         * @param parent A reference to the parent container component of this component
140
         */
141
        public WFSFilterPanel(WFSParamsPanel parent) {
142
                super();
143
                this.parent = parent;
144
                currentPath = null;
145
                featureName = null;
146
                allFieldsAndValuesKnownOfCurrentLayer = new HashMap(); // Initial capacity = 0
147

    
148
                // At beginning, the JList is disabled (and its set a particular color for user could knew it)
149
                super.getValuesJList().setEnabled(false);
150
                getValuesJList().setBackground(new Color(220, 220, 220));
151
        }
152
        
153
        /*
154
         *  (non-Javadoc)
155
         * @see org.gvsig.gui.beans.filterPanel.AbstractFilterQueryJPanel#initialize()
156
         */
157
        protected void initialize() {
158
                super.initialize();
159
                this.resizeHeight(380);
160

    
161
                defaultTreeModel = (DefaultTreeModel)fieldsJTree.getModel();
162
                
163
                this.addNewListeners();
164
                panelAsATabForWFSLayersLoad = true;                
165
        }
166
        
167
        /**
168
         * Adds some more listener to the components of the panel
169
         */
170
        private void addNewListeners() {
171
                
172
                // Enable "Apply" button when user changes the filter query
173
                txtExpression.getDocument().addDocumentListener(new DocumentListener() {
174
                        /*
175
                         *  (non-Javadoc)
176
                         * @see javax.swing.event.DocumentListener#changedUpdate(javax.swing.event.DocumentEvent)
177
                         */
178
                        public void changedUpdate(DocumentEvent e) {
179
                        }
180

    
181
                        /*
182
                         *  (non-Javadoc)
183
                         * @see javax.swing.event.DocumentListener#insertUpdate(javax.swing.event.DocumentEvent)
184
                         */
185
                        public void insertUpdate(DocumentEvent e) {
186
                                if (!panelAsATabForWFSLayersLoad)
187
                                        parent.isApplicable(true);
188
                        }
189

    
190
                        /*
191
                         *  (non-Javadoc)
192
                         * @see javax.swing.event.DocumentListener#removeUpdate(javax.swing.event.DocumentEvent)
193
                         */
194
                        public void removeUpdate(DocumentEvent e) {
195
                                if (!panelAsATabForWFSLayersLoad)
196
                                        parent.isApplicable(true);
197
                        }
198
                });
199
                
200
                // Listener for "fieldsJTree" 
201
                getFieldsJTree().addMouseListener(new MouseAdapter() {
202
                        /*
203
                         *  (non-Javadoc)
204
                         * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
205
                         */
206
                        public void mouseClicked(MouseEvent e) {
207
                                int row = fieldsJTree.getRowForLocation(e.getX(), e.getY());
208
                                TreePath treePath = fieldsJTree.getPathForLocation(e.getX(), e.getY());
209

    
210
                                if (row > -1) {
211
                                        switch (e.getClickCount()) {
212
                                                case 2:                                                        
213
                                                        putSymbolOfSelectedByMouseBranch(treePath);
214
                                                        break;
215
                                        }
216
                                }
217
                        }
218
                });
219
                
220
                // Listener for "valuesJList"
221
                getValuesJList().addMouseListener(new MouseAdapter() {
222
                        /*
223
                         *  (non-Javadoc)
224
                         * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
225
                         */
226
                        public void mouseClicked(MouseEvent e) {
227
                                int index = getValuesJList().getSelectedIndex();
228
                                                
229
                                if (index == -1)
230
                                        return;
231
                                        
232
                                if (e.getClickCount() == 2){
233
                                        String valor = ((JLabel) valuesListModel.getElementAt(index)).getText();
234
                                        
235
                                        // If value is an string -> set it between apostrophes
236
                                        if (getNodeOfCurrentPath().getEntityType().getName().compareTo("xs:string") == 0) {
237
                                                putSymbol("'" + valor + "'");
238
                                        }
239
                                        else {
240
                                                putSymbol(valor);
241
                                        }
242
                                }
243
                        }
244
                });
245
                
246
                // Listener for a branch of the tree selection
247
                getFieldsJTree().addTreeSelectionListener(new TreeSelectionListener() {
248
                        /*
249
                         *  (non-Javadoc)
250
                         * @see javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event.TreeSelectionEvent)
251
                         */
252
                        public void valueChanged(TreeSelectionEvent e) {
253
                                if (!panelAsATabForWFSLayersLoad) {                                        
254
                                        DataReturnedOfDataLoadingFromActiveView data = DataLoadingFromActiveView.getDefaultExpressionDataSource();
255
                
256
                                        if ((data != null) && (data.getData() != null)) {
257
//                                                setModel(data.getData());
258
                                                currentPath = e.getPath();
259
                                                fillValuesByPath(currentPath);
260
                                        }
261
                                }
262
                        }                        
263
                });                
264
        }
265
        
266
        /**
267
         * Gets the element that the 'currentPath' attribute aims
268
         * 
269
         * @return An XMLElement
270
         */
271
        private XMLElement getNodeOfCurrentPath() {
272
                
273
                if (currentPath != null) {
274
                        Object node = currentPath.getLastPathComponent();
275
                        
276
                        if ((node != null) && (node instanceof XMLElement)) {
277
//                                XMLElement element = (XMLElement) node;
278
                                return (XMLElement) node;
279
                        }
280
                }
281
                
282
                return null;
283
        }
284
        
285
        /**
286
         * Puts the symbol of selected brach
287
         * 
288
         * @param mouseEvent A MouseEvent with information  of the selected branch
289
         */
290
        public void putSymbolOfSelectedByMouseBranch(TreePath treePath) {
291
                // Sets the node selected
292
                if (treePath != null) {
293
                        Object node = treePath.getLastPathComponent();
294
                        if ((node != null) && (node instanceof XMLElement)) {
295
                                XMLElement element = (XMLElement) node;
296
                                XMLElement parent = element.getParentElement();
297
                                String path = element.getName();
298
                                while (parent.getParentElement() != null){
299
                                        path = parent.getName() + "/" + path;
300
                                        parent = parent.getParentElement();
301
                                }
302
                                putSymbol("\"" + path + "\"");
303
                        }
304
                }
305
        }
306
        
307
        /**
308
         * Gets the value of the inner attribute: 'panelAsATabForWFSLayersLoad'
309
         * 
310
         * @return A boolean value
311
         */
312
        public boolean getWFSFilterPanelIsAsTabForWFSLayersLoad() {
313
                return this.panelAsATabForWFSLayersLoad;
314
        }
315
        
316
        /**
317
         * Sets the value of the inner attribute: 'panelAsATabForWFSLayersLoad'
318
         * 
319
         * @param b A boolean value
320
         */
321
        public void setWFSFilterPanelIsAsTabForWFSLayersLoad (boolean b) {
322
                this.panelAsATabForWFSLayersLoad = b;
323
                
324
                if (this.panelAsATabForWFSLayersLoad == true) {
325
                        // At beginning, the JList is disabled (and its set a particular color for user could knew it)
326
                        super.getValuesJList().setEnabled(false);
327
                        super.getValuesJList().setBackground(new Color(220, 220, 220)); // a grey color
328
                        
329
                        this.allFieldsAndValuesKnownOfCurrentLayer.clear();
330
                }
331
                else {
332
                        // Unselect the selected path in the tree (if there was any selected)
333
                        if (this.currentPath != null) {
334
                                this.currentPath = null;
335
                                this.getFieldsJTree().removeSelectionPath(this.getFieldsJTree().getSelectionPath());
336
                        }
337
                        
338
                        // Resets data loaded
339
                        super.getValuesJList().setEnabled(true);
340
                        super.getValuesJList().setBackground(Color.WHITE);
341
                        
342
                        this.getFieldsJTree().removeAll();
343
                        this.getValuesJList().removeAll();
344
                        
345
                        // Updates data associated to view with the new layer data
346
                        this.setNewDataToTable();
347
                        
348
                        // If theres is any table associated to the current view -> update that table/s
349
//                        this.updateTablesThatHasNewData();
350
                        
351
                        // Reads that new data
352
                        DataReturnedOfDataLoadingFromActiveView data = DataLoadingFromActiveView.getDefaultExpressionDataSource();
353
                        
354
                        if ((data != null) && (data.getData() != null)) {
355
                                setModel(data.getData());
356
//                                currentPath = e.getPath();
357
//                                fillValuesByPath(currentPath);
358
                        }
359
                        
360
                        // Loads values known of fields
361
                        this.setValuesKnownOfFields();
362
                }
363
        }
364
        
365
        /**
366
         * Refresh all information about fields
367
         * 
368
         * @param feature
369
         */
370
        public void refresh(WFSLayerNode feature) {
371
                featureName = feature.getTitle();
372
                setFields(feature);
373
        }
374
        
375
        ///// END GUI METHODS /////
376

    
377
        ///// METHODS FOR THE FILTER QUERY /////
378
        
379
        /**
380
         * Gets the query that will be send to the server
381
         * @return SQL query (just the where part)
382
         */
383
        public String getQuery(){
384
//                // Codify the query
385
//                String queryCodified = this.codifyExpression(txtExpression.getText().trim()); // Ignores the spaces at beginning and end of the chain of characters
386
//                        
387
//                // Validate expression
388
//                return this.validateExpression(queryCodified);
389
                // Codify the query
390
                String queryCodified = this.validateExpression(txtExpression.getText().trim());
391
                        
392
                // Validate expression
393
                return this.codifyExpression(queryCodified); // Ignores the spaces at beginning and end of the chain of characters
394

    
395
        }
396
        
397
        /**
398
         * Gets the filter expression from the user interface
399
         */
400
        public String getFilterExpressionFromInterface() {
401
                return getTxtExpression().getText();
402
        }
403
        
404
        /**
405
         * Writes the filter expression into the user interface
406
         * @param filterExpression An string
407
         */
408
        public void setFilterExpressionIntoInterface(String filterExpression){
409
                getTxtExpression().setText(filterExpression);
410
        }
411
        
412
        /**
413
         * Codifies the expression to ISO ISO-8859_1 and a format that the SQL parser could validate
414
         * 
415
         * @param expression The expression to be codified 
416
         * 
417
         * @return The expression codified
418
         */
419
        private String codifyExpression(String expression) {
420
                String result = new String("");
421
                
422
                /* CODIFICATION OF THE QUERY SINCE WHERE */
423
                try
424
                {                        
425
                        // Encode each string of the query
426
                        int index = 0;
427
                        int lastIndex = 0;
428
                        boolean endInnerLoop;
429
                        // Encodes all inner strings to the equivalent codification in ISO-8859_1 with each ' symbol converted to ''
430
                        while (index != -1) {
431
                                index = expression.indexOf("'", index);
432
                                
433
                                // Add the parts of the chain of characters that not are string
434
                                if (index == -1) {
435
                                        result += expression.substring(lastIndex, expression.length());
436
                                }
437
                                else {
438
                                        result += expression.substring(lastIndex, index).replaceAll(" [ ]+", " ");
439
                                }
440
                                
441
                                lastIndex = index;
442
                                endInnerLoop = false;
443
                                
444
                                // Tries to find each first apostrophe of each string of the query
445
                                if ((index > 0) && (expression.charAt(index - 1) == ' ')) {
446
                                        index++;
447
                                        
448
                                        // Ignore all inner apostrophes and try to find the last of the string
449
                                        while (!endInnerLoop)  {
450
                                                index = expression.indexOf("'", index);
451
                                                index++;
452
                                                
453
                                                // If we haven't arrived to the finish of the string
454
                                                if (index != expression.length()) {
455
                                                        if ((index == -1) || (expression.charAt(index) == ' ')) {
456
                                                                result += translateString(expression.substring(lastIndex, index));
457
                                                                endInnerLoop = true;
458
                                                        }
459
                                                }
460
                                                else {
461
                                                        result += translateString(expression.substring(lastIndex, index));
462
                                                        endInnerLoop = true;
463
                                                        index = -1; // Force to finish the external loop
464
                                                }
465
                                        }
466
                                        lastIndex = index;
467
                                }
468
                        }
469
                        
470
                        // Field names are transformated in xix variables that will be analyzed
471
                        // Date(date) is substituted by the correct date format
472
                        result = translateDates(result);
473
                        result = translateNumber(result);
474
                        result = translateWord(result, "true", "1");
475
                        result = translateWord(result, "false", "0");
476
        
477
                        logger.debug(result);                        
478
                }
479
                catch(Exception e) {
480
                        JOptionPane.showMessageDialog(this, Messages.getText("error_coding_filter_query"), Messages.getText("error"), JOptionPane.ERROR_MESSAGE);
481
                        return null;
482
                }                
483
                /* END CODIFICATION OF THE QUERY SINCE WHERE */
484

    
485
                return result;
486
        }
487
        
488
        /**
489
         * Checks the expression if it's correct according a SQL parser
490
         * 
491
         * @param query The query expression to analyze
492
         * @return An string, or 'null' if there has been an error
493
         */
494
        private String validateExpression(String query) {
495
                
496
                /* VALIDATE SQL EXPRESSION SINCE WHERE */
497
                String result = SQLExpressionFormatForFilterGUI.validateSQLquery(query);
498
                /* END VALIDATE SQL EXPRESSION SINCE WHERE */        
499

    
500
                return result;
501
        }
502
        
503
        /**
504
         * DOCUMENT ME!
505
         *
506
         * @return DOCUMENT ME!
507
         *
508
         * @throws ParseException DOCUMENT ME!
509
         * @deprecated In this moments its a reference of the old Validate Expression method
510
         */
511
        private String oldValidateExpressionMethod() throws ParseException {
512
                String expression = txtExpression.getText();
513
//                HashSet variablesIndexes = new HashSet();
514
//
515
//                StringBuffer traducida = new StringBuffer();
516

    
517
                //Se transforman los nombres de los campos en las variables xix que analizar?n
518
                //Se quitan los Date(fecha) y se mete la fecha correspondiente
519
                expression = translateDates(expression);
520
                expression = translateNumber(expression);
521
                expression = translateWord(expression, "true", "1");
522
                expression = translateWord(expression, "false", "0");
523

    
524
                String replacement;
525
                Pattern patron = Pattern.compile("[^<>!]=");
526
                Matcher m = patron.matcher(expression);
527
                int index = 0;
528

    
529
                while (m.find(index)) {
530
                        index = m.start();
531
                        replacement = expression.charAt(index) + "==";
532
                        m.replaceFirst(replacement);
533
                        index++;
534
                }
535

    
536
                expression = expression.replaceAll("[^<>!]=", "==");
537

    
538
                logger.debug(expression);
539

    
540
                return expression;
541
        }
542
        
543
        ///// END METHODS FOR THE FILTER QUERY /////
544

    
545
        ///// METHODS FOR TRANSLATE DATA IN FILTER SENTENCES /////
546

    
547
        /** 
548
         * DOCUMENT ME!
549
         *
550
         * @param expresion DOCUMENT ME!
551
         * @param word DOCUMENT ME!
552
         * @param translation DOCUMENT ME!
553
         *
554
         * @return DOCUMENT ME!
555
         *
556
         * @throws ParseException DOCUMENT ME!
557
         */
558
        private String translateWord(String expresion, String word,        String translation) throws ParseException {
559
                int booleanIndex = 0;
560
                int endIndex = 0;
561
                StringBuffer res = new StringBuffer();
562

    
563
                while ((booleanIndex = getIndex(expresion, word, booleanIndex)) != -1) {
564
                        res.append(expresion.substring(endIndex, booleanIndex));
565
                        endIndex = booleanIndex + word.length();
566
                        booleanIndex++;
567
                        res.append(translation);
568
                }
569

    
570
                if (endIndex < expresion.length()) {
571
                        res.append(expresion.substring(endIndex));
572
                }
573

    
574
                return res.toString();
575
        }
576

    
577
        /**
578
         * DOCUMENT ME!
579
         *
580
         * @param expresion DOCUMENT ME!
581
         *
582
         * @return DOCUMENT ME!
583
         *
584
         * @throws ParseException DOCUMENT ME!
585
         */
586
        private String translateDates(String expresion) throws ParseException {
587
                //Se obtiene el valor de la fecha
588
                String date = StringUtilities.substringDelimited(expresion, "Date(", ")", 0);
589

    
590
                if (date == null) {
591
                        return expresion;
592
                }
593

    
594
                //Se comprueba que no est? entre comillas 
595
                int startIndex = expresion.indexOf(date);
596

    
597
                while (startIndex != -1) {
598
                        if (!StringUtilities.isBetweenSymbols(expresion, startIndex, "\"")) {
599
                                
600
                                //Se sustituye por el valor ordinal de la fecha
601
                                expresion = expresion.substring(0, startIndex - 5) +
602
                                        expresion.substring(startIndex).replaceFirst(date + "\\)",
603
                                                new Long((filterButtonsJPanel.getDateFormat().parse(date)).getTime()).toString());
604

    
605
                        } else {
606
                                startIndex += date.length();
607
                        }
608
                        
609
                        if (date == null) {
610
                                return expresion;
611
                        }
612

    
613
                        startIndex = expresion.indexOf(date, startIndex);
614
                }
615

    
616
                return expresion;
617
        }
618

    
619
        /**
620
         * DOCUMENT ME!
621
         *
622
         * @param expresion DOCUMENT ME!
623
         *
624
         * @return DOCUMENT ME!
625
         *
626
         * @throws ParseException DOCUMENT ME!
627
         */
628
        private String translateNumber(String expresion) throws ParseException {
629
                DefaultCharSet ss = new DefaultCharSet();
630
                ss.addInterval('0', '9');
631
                ss.addCharacter(',');
632
                ss.addCharacter('.');
633

    
634
                String number = StringUtilities.substringWithSymbols(expresion, ss, 0);
635

    
636
                if (number == null) {
637
                        return expresion;
638
                }
639

    
640
                int startIndex = expresion.indexOf(number);
641

    
642
                while (startIndex != -1) {
643
                        Number n = nf.parse(number);
644

    
645
                        if (!StringUtilities.isBetweenSymbols(expresion, startIndex, "\"")) {
646
                                
647
                                //Se sustituye por el valor ordinal de la fecha
648
                                expresion = expresion.substring(0, startIndex) +
649
                                        expresion.substring(startIndex).replaceFirst(number,
650
                                                n.toString());
651
                        } else {
652
                                startIndex += n.toString().length();
653
                        }
654

    
655
                        number = StringUtilities.substringWithSymbols(expresion, ss,
656
                                        startIndex);
657

    
658
                        if (number == null) {
659
                                return expresion;
660
                        }
661

    
662
                        startIndex = expresion.indexOf(number, startIndex);
663
                }
664

    
665
                return expresion;
666
        }
667
        
668
        /**
669
         * Encodes an string to ISO 8859_1 with each ' symbol converted to '' 
670
         * 
671
         * @param text An string started and finished with simple apostrophes
672
         * 
673
         * @return An string started and finished with simple apostrophes
674
         */
675
        private String translateString(String text) {
676
                // Encode to the string to ISO 8859_1 (the URL codification)
677
                try {
678
                        
679
                        // Ignore the first and last apostrophes
680
                        if (text.length() > 2) {
681
                                text = text.substring(1, text.length() -1);
682
                                
683
                                // Convert the string to ISO 8859_1 codification
684
                                text = URLEncoder.encode(text, "8859_1");
685
                                
686
                                // Change '  (%27 code) to '' for the SQL parser (bebore sent the query)
687
                                text = text.replaceAll("\\%27", "\\'\\'");
688
                        }
689

    
690
                } catch (UnsupportedEncodingException e1) {
691
                        e1.printStackTrace();
692
                }
693
                
694
                return "'" + text + "'";
695
        }
696
        
697
        ///// END METHODS FOR TRANSLATE DATA IN FILTER SENTENCES /////
698
        
699
        ///// METHODS FOR MANIPULATE 'fields' and 'values' /////
700
        
701
        /**
702
         * DOCUMENT ME!
703
         *
704
         * @param t DOCUMENT ME!
705
         */
706
        public void setModel(ExpressionDataSource t) {
707
                try {
708
                        model = t;
709
            model.start();
710
        } catch (DriverException e1) {
711
            NotificationManager.addError(e1.getMessage(), e1);
712
        }
713

    
714
        try {
715
                int numberOfFields = model.getFieldCount();
716

    
717
                if (numberOfFields > 0) {
718
                        Vector fields = new Vector(0, 1);
719
                        int j = 0;
720
                
721
                                for (int i = 0; i < numberOfFields; i++) {
722
                                         Object field = model.getFieldName(i);
723
                                        
724
                                        if (field != null) {
725
                                                fields.add(field);
726
                                                j++;
727
                                        }
728
                                }
729
                        
730
                                attributesTreeTableModel = new AttributesTreeTableModel(fields.toArray());                        
731
                }
732
                } catch (FilterException e) {
733
                        throwException(e);
734
                }
735
        }
736
        
737
        /**
738
         * If there is a field selected, show its new values
739
         */
740
        public void updateFieldValues() {
741
                if (currentPath != null) {
742
                        
743
                        DataReturnedOfDataLoadingFromActiveView data = DataLoadingFromActiveView.getDefaultExpressionDataSource();
744
                                                
745
                        if ((data != null) && (data.getData() != null)) {
746
                                setModel(data.getData());                                
747
                                fillValuesByPath(currentPath);
748
                                
749
//                                valuesListModel.clear();
750
                                
751
                                // Updates all tables that their data is about the changed view
752
                                this.updateTablesThatHasNewData();
753
                        }
754
                }
755
        }
756
        
757
        /**
758
         * Sets Fields
759
         *
760
         * @param feature A Layer node with fields information
761
         */
762
        private void setFields(WFSLayerNode feature) {
763
                Vector fields = feature.getFields();
764
                                
765
                this.resetFieldsAndValuesData();
766
                
767
                int numberOfFields = fields.size();
768
                
769
                if (numberOfFields > 0) {
770
                        Vector fieldBranches = new Vector(0, 1);
771
                        
772
                        for (int i=0; i<fields.size(); i++) {
773
                                XMLElement field = (XMLElement)fields.get(i);
774

    
775
                                IXMLType type = field.getEntityType();
776
                                
777
                                if (type != null) {                                        
778
                                        
779
                                        switch (type.getType()) {
780
                                                case IXMLType.GML_GEOMETRY: // Don't add branch / field
781
                                                        break;
782
                                                case IXMLType.COMPLEX: case IXMLType.SIMPLE: // Add branch / field
783
                                                        fieldBranches.add(field);
784
                                                        
785
                                                        break;
786
                                        }
787
                                }
788
                        }
789
                        
790
                        attributesTreeTableModel = new AttributesTreeTableModel(fieldBranches.get(0));
791
                        fieldsJTree.setModel(new AttributesTreeTableModel(fieldBranches.get(0), false));
792
                        
793
                        // Stores the name of all leafs (fields) of treeTableModel                        
794
                        Object root = attributesTreeTableModel.getRoot();
795
                        
796
                        if (root != null) {
797
                                Vector fieldsNames = attributesTreeTableModel.getLeafsFromNodeBranch(root);
798
                                
799
                                for (int j = 0; j < fieldsNames.size(); j++) {
800
                                        Object field = fieldsNames.get(j);
801
                                        
802
                                        // Avoid errors
803
                                        if ( (! (field instanceof XMLElement)) || (field == null) )
804
                                                continue;
805
                                        
806
                                        // Don't load a geometry field                                        
807
                                        if ( ((XMLElement)field).getEntityType().getType() == IXMLType.GML_GEOMETRY )
808
                                                continue;                                        
809
                                        
810
                                        if (! allFieldsAndValuesKnownOfCurrentLayer.containsKey( ((XMLElement)field).getName()) ) {
811
                                                allFieldsAndValuesKnownOfCurrentLayer.put(((XMLElement)field).getName(), new HashMap());
812
                                        }
813
                                }
814
                        }
815
                }
816
        }
817

    
818
        /**
819
         * This method load all values known of all fields known
820
         * (It's used when a new layer is load)
821
         */
822
        private void setValuesKnownOfFields() {
823
                // Desde el modelo se deber?a acceder a los campos y sus valores cargados                
824
                try {
825
                        for (int i = 0; i < model.getFieldCount(); i++) {
826
                                String fieldName = model.getFieldName(i);
827
                                HashMap fieldValues = (HashMap) allFieldsAndValuesKnownOfCurrentLayer.get(fieldName);
828
                                
829
                                if (fieldValues != null) {
830
                                        for (int j = 0; j < model.getRowCount(); j++) {
831
                                                Value value = model.getFieldValue(j, i);                                        
832
                                                
833
                                                if (value instanceof NullValue)
834
                                                    continue;
835
                                                
836
                                                Object obj = (Object)value;
837
                                                
838
                                                if (obj == null)
839
                                                        continue;
840
                                                
841
                                                fieldValues.put(obj.toString(), obj.toString());
842
                                                
843
                                        }
844
                                }
845
                        }
846
                }
847
                catch (Exception e) {
848
                        e.printStackTrace();
849
                }
850
        }
851
        
852
        /**
853
         * Resets the data of fields and their values of the current layer feature, and removes the branches of JTree
854
         */
855
        private void resetFieldsAndValuesData() {
856
                fieldsJTree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode()));
857
                txtExpression.setText("");
858
                ((DefaultListModel)valuesJList.getModel()).removeAllElements();
859
        }
860
        
861
        /** 
862
         * FIlls list with the values of selected field
863
         * 
864
         * @param treePath A path in the tree
865
         */
866
        private void fillValuesByPath(TreePath treePath) {
867
                // Duplicates are removed
868
                TreeSet conjunto = new TreeSet(new Comparator() {
869
                        public int compare(Object o1, Object o2) {
870
                                if ((o1 != null) && (o2 != null)) {
871
                                        Value v2 = (Value) o2;
872
                                        Value v1 = (Value) o1;
873
                                        BooleanValue boolVal;
874
                                        
875
                                        try {
876
                                                boolVal = (BooleanValue) (v1.greater(v2));
877
                                                
878
                                                if (boolVal.getValue()) {
879
                                                        return 1;
880
                                                }
881
                                                
882
                                                boolVal = (BooleanValue) (v1.less(v2));
883
                                                
884
                                                if (boolVal.getValue()) {
885
                                                        return -1;
886
                                                }
887
                                        } catch (IncompatibleTypesException e) {
888
                                                throw new RuntimeException(e);
889
                                        }
890
                                }
891
                                
892
                                return 0;
893
                        }
894
                }); // For ordernation
895
                
896
                // Remove the previous items
897
                valuesListModel.clear();
898
                
899
                try {
900
                        //Object root = treePath.getPath()[0];
901
                        XMLElement element = ((XMLElement)treePath.getLastPathComponent());
902
                        
903
                        // Gets the values associated to the selected branch 
904
                        switch (element.getEntityType().getType()) {
905
                                case IXMLType.SIMPLE:
906
                                        
907
                                        if(element.getParentElement().getParentElement() == null) {                                        
908
                                                // Find the selected field and try to obtein values related
909
                                                for (int i = 0; i < model.getFieldCount(); i++) {                                        
910
                                                        String name = model.getFieldName(i);
911
                                                        
912
                                                        // If we find the field (this means that are loaded its values and we can obtein them)
913
                                                        if (name.equals(element.getName())) {                                                
914
                                                                for (int j = 0; j < model.getRowCount(); j++) {                                        
915
                                                                        Value value = model.getFieldValue(j, i);
916
                                                                        
917
                                                                        if (value instanceof NullValue)
918
                                                                            continue;
919
                                                                        
920
                                                                        if (!conjunto.contains(value)) {
921
                                                                                conjunto.add(value);
922
                                                                        }
923
                                                                }
924
                                                                
925
                                                                break;
926
                                                        }
927
                                                }
928
                                        }else{
929
                                                //create a vector with the parent names from the leaf until the root
930
                                                XMLElement parent = element.getParentElement();
931
                                                Vector parentNames = new Vector();
932
                                                parentNames.add(element.getName());
933
                                                while (parent != null){
934
                                                        parentNames.add(parent.getName());
935
                                                        parent = parent.getParentElement();                                                        
936
                                                }
937
                                                
938
                                                //The field name (in the gvSIG table) is the second field name
939
                                                String fieldName = (String)parentNames.get(parentNames.size()-2);
940
                                                
941
                                                for (int i = 0; i < model.getFieldCount(); i++) {                                        
942
                                                        String name = model.getFieldName(i);
943
                                                        
944
                                                        // If we find the field (this means that are loaded its values and we can obtein them)
945
                                                        if (name.equals(fieldName)) {                                                
946
                                                                for (int j = 0; j < model.getRowCount(); j++) {                                        
947
                                                                        Value value = model.getFieldValue(j, i);
948
                                                                                                                        
949
                                                                        if (value instanceof NullValue)
950
                                                                            continue;
951
                                                                        
952
                                                                        if (value instanceof ComplexValue){
953
                                                                                for (int k=parentNames.size()-3 ; k>=0 ; k--){
954
                                                                                        ComplexValue complex = (ComplexValue)value;
955
                                                                                        Value childValue = (Value)complex.get(parentNames.get(k));
956
                                                                                        if (k==0){
957
                                                                                                if (!conjunto.contains(childValue)) {
958
                                                                                                        conjunto.add(childValue);
959
                                                                                                }
960
                                                                                        }else{
961
                                                                                                value = childValue;
962
                                                                                        }
963
                                                                                }
964
                                                                        }
965
                                                                }
966
                                                                
967
                                                                break;
968
                                                        }
969
                                                }
970
                                        }
971
                                        break;
972
                                case IXMLType.COMPLEX:
973
                                        break;
974
                                default:
975
                                        // Do Nothing
976
                        }
977
                        
978
                        // Add the values to the model of the graphic list
979
                        Iterator it = conjunto.iterator();
980
                        Object[] objects = currentPath.getPath();
981

    
982
                        if (objects.length == 0)
983
                                return;
984
                        
985
                        String selectedField = ((XMLElement)objects[objects.length-1]).getName(); // Gets the selected field
986
                        
987
                        if (selectedField != null) { // If there is a selected field
988
                                Map fieldValues = (HashMap)allFieldsAndValuesKnownOfCurrentLayer.get(selectedField); // Gets valus stored associated to this field
989
                                JLabel currentValueLabel = null;
990
                                
991
                                // If the field doesn't exits -> create a new Map with its values
992
                                if (fieldValues == null) {
993
                                        fieldValues = new HashMap();
994
                                        allFieldsAndValuesKnownOfCurrentLayer.put(selectedField, fieldValues);        
995
                                
996
                                        while (it.hasNext()) {
997
                                                // A label with text with yelow background color for values that are loaded in the layer
998
                                                currentValueLabel = new JLabelValueLoaded();
999
                                                
1000
                                                currentValueLabel.setText(it.next().toString());
1001
                                                
1002
                                                if (currentValueLabel.getText().compareTo("") != 0) {                                                                                
1003
                                                        fieldValues.put(currentValueLabel.getText(), currentValueLabel.getText());
1004
                                                
1005
                                                        // All values loaded in this loop must be at beginning of the list (and in a differenciated color)
1006
                                                        if ( ! valuesListModel.contains(currentValueLabel) )
1007
                                                                valuesListModel.addElement(currentValueLabel);                                                        
1008
                                                }
1009
                                        }
1010
                                }
1011
                                else { // Else -> Adds the new ones, and changes element labels that have changed  (before were loaded and now not, or before weren't loaded but now yes)
1012
                                        
1013
                                        // Changes element labels that have changed  (before were loaded and now not, or before weren't loaded but now yes)
1014
                                        ((DefaultListModelForJLabelAsCell)valuesListModel).setAllElementsToNotLoaded();
1015
                                        
1016
                                        // For each current value associated to de current selected field -> if its loaded -> put it at beginning of the list and change to 'JLabelLoadedValue' 
1017
                                        while (it.hasNext()) {
1018
                                                String text = it.next().toString();
1019
                                                int elementPosition = ((DefaultListModelForJLabelAsCell)valuesListModel).getIndexOfJLabelText(text);
1020
                                                
1021
//                                                if (! ((DefaultListModelForJLabelAsCell)valuesListModel).containsJLabelText(text) )
1022
                                                if (elementPosition == -1) // If it must be added                                                
1023
                                                        valuesListModel.addElement(new JLabelValueLoaded(text));
1024
                                                else
1025
                                                        ((DefaultListModelForJLabelAsCell)valuesListModel).changeElementThatHasTextToJLabelLoadedValue(text); // Change to 'JLabelLoadedValue'
1026
                                                
1027
                                                        
1028
//                                                // A label with text with yellow background color for values that are loaded in the layer
1029
//                                                currentValueLabel = new JLabelValueLoaded();
1030
//                                                
1031
//                                                currentValueLabel.setText(it.next().toString());                                                                                        
1032
//                                                
1033
//                                                
1034
//                                                if ( ! fieldValues.containsKey(currentValueLabel.getText()) ) {
1035
//                                                        fieldValues.put(currentValueLabel.getText(), currentValueLabel.getText());
1036
//                                                }
1037
//                                                
1038
//                                                // All values loaded in this loop must be at beginning of the list (and in a differenciated color)
1039
//                                                if ( ! (valuesListModel).contains(currentValueLabel) )
1040
//                                                        valuesListModel.addElement(currentValueLabel);
1041
//                                                
1042
//                                                else
1043
                                        }
1044
                                }
1045
                        
1046
                                // Load the rest of the values associated to the current selected field
1047
                                if (fieldValues != null) {
1048
                                        // A label with text with yelow background color for values that are loaded in the layer
1049
                                        currentValueLabel = new JLabelValueNotLoaded();
1050

    
1051
                                        Set values = fieldValues.keySet();
1052

    
1053
                                        it = values.iterator();
1054

    
1055
                                        while (it.hasNext()) {
1056
                                                String name = it.next().toString();
1057
                                                
1058
                                                if ( ! ((DefaultListModelForJLabelAsCell)valuesListModel).containsJLabelText(name) )
1059
                                                        valuesListModel.addElement(new JLabelValueNotLoaded(name));
1060
                                        }
1061
                                }
1062
                        }
1063
                        
1064
                } catch (Exception e) {
1065
                        throwException(e);
1066
                }
1067
        }
1068
        
1069
        ///// END METHODS FOR MANIPULATE 'fields' and 'values' /////
1070
        
1071
        ///// METHODS FOR PARENT NOTIFICATIONS /////
1072
        
1073
        /**
1074
         * @see WFSParamsPanel#isApplicable(boolean)
1075
         * 
1076
         * This also loads values of fields 
1077
         * 
1078
         * @param b A boolean value
1079
         */
1080
        private void setApplicate(boolean b) {
1081
                parent.isApplicable(b);
1082
        }
1083
        
1084
        ///// END METHODS FOR PARENT NOTIFICATIONS /////
1085
        
1086
        ///// METHOS FOR 'allFieldsAndValuesKnownOfCurrentLayer' /////
1087
        
1088
        /**
1089
         * Sets all fields and values known about the current layer
1090
         * 
1091
         * @param _allFieldsAndValuesKnownOfCurrentLayer A Map object
1092
         */
1093
        public void setAllFieldsAndValuesKnownOfCurrentLayer(Map _allFieldsAndValuesKnownOfCurrentLayer) {
1094
                if (_allFieldsAndValuesKnownOfCurrentLayer == null)
1095
                        this.allFieldsAndValuesKnownOfCurrentLayer = new HashMap();
1096
                else
1097
                        this.allFieldsAndValuesKnownOfCurrentLayer = _allFieldsAndValuesKnownOfCurrentLayer;
1098
        }
1099
        
1100
        /**
1101
         * Gets all fields and values known about the current layer
1102
         * 
1103
         * @return _allFieldsAndValuesKnownOfCurrentLayer A Map object
1104
         */
1105
        public Map getAllFieldsAndValuesKnownOfCurrentLayer() {
1106
                return allFieldsAndValuesKnownOfCurrentLayer;
1107
        }
1108
        
1109
        ///// METHOS FOR 'allFieldsAndValuesKnownOfCurrentLayer' /////
1110
        
1111
        ///// IMPLEMENTATION OF METHODS OF 'IWindowListener' /////
1112
        
1113
    /* (non-Javadoc)
1114
     * @see com.iver.andami.ui.mdiManager.ViewListener#viewActivated()
1115
     */
1116
    public void windowActivated() {
1117
    }
1118

    
1119
    /* (non-Javadoc)
1120
     * @see com.iver.andami.ui.mdiManager.ViewListener#viewClosed()
1121
     */
1122
    public void windowClosed() {
1123
        try {
1124
            model.stop();
1125
        } catch (DriverException e) {
1126
            NotificationManager.addError(e.getMessage(), e);
1127
        }        
1128
    }
1129
    
1130
    ///// END IMPLEMENTATION OF METHODS OF 'IWindowListener' /////
1131

    
1132
        ///// IMPLEMENTATION OF METHODS OF 'IWindow' /////    
1133
    
1134
    /*
1135
     *  (non-Javadoc)
1136
     * @see com.iver.andami.ui.mdiManager.IWindow#getWindowInfo()
1137
     */
1138
        public WindowInfo getWindowInfo() {
1139
                return null;
1140
        }
1141
        
1142
        ///// END IMPLEMENTATION OF METHODS OF 'IWindow' /////
1143
        
1144
        ///// UPDATE TABLES DATA /////
1145
        
1146
        /**
1147
         * Updates all tables that their data is about the changed view
1148
         */
1149
        private void updateTablesThatHasNewData() {
1150
                boolean oneTimeNewDataToTableAdded = false;
1151
                
1152
                IWindow[] activeNoModalWindows = PluginServices.getMDIManager().getAllWindows();
1153
                
1154
                for (int i = 0; i < activeNoModalWindows.length; i++) {
1155
                        IWindow window = activeNoModalWindows[i];
1156
                        if (window instanceof Table) {
1157
                                Table table = (Table) window;
1158
                                
1159
                                int pos1 = featureName.indexOf(':');
1160
                                
1161
                                if ((pos1 >= 0) && (pos1 < featureName.length()))                                                
1162
                                        featureName = featureName.substring(pos1 +1, featureName.length());
1163
                                
1164
//                                        String featureOfTable = ((XMLElement)currentPath.getParentPath().getLastPathComponent()).getName();
1165
                                        String featureOfTable = table.getModel().getName();
1166
                                        int pos2 = featureOfTable.indexOf(':');
1167
                                                                                                
1168
                                        if ((pos2 >= 0) && (pos2 < featureName.length()))
1169
                                                featureOfTable = featureOfTable.substring(pos2 +1, featureOfTable.length());                                                
1170
                                
1171
                                if (featureName.trim().compareTo(featureOfTable.trim()) == 0) {
1172
                                        // Only add the new data associated to the table one time
1173
                                        if (oneTimeNewDataToTableAdded == false) {
1174
                                                setNewDataToTable();
1175
                                                oneTimeNewDataToTableAdded = true;
1176
                                        }
1177
                                
1178
                                        // Refresh the table with the new data
1179
                                        table.refresh();
1180
                                }
1181
                        }
1182
                }                
1183
        }        
1184
        
1185
        /**
1186
         * This method is a modification of the "execute" method from the "ShowTable" class 
1187
         *
1188
         * @see com.iver.cit.gvsig.ShowTable#execute(String)
1189
         */
1190
        private void setNewDataToTable() {
1191
                View vista = (View) PluginServices.getMDIManager().getActiveWindow();
1192
                FLayer[] actives = vista.getModel().getMapContext().getLayers().getActives();
1193

    
1194
                try {
1195
                        for (int i = 0; i < actives.length; i++) {
1196
                                if (actives[i] instanceof AlphanumericData) {
1197
                                        AlphanumericData co = (AlphanumericData) actives[i];
1198

    
1199
                                        //SelectableDataSource dataSource;
1200
                                        //dataSource = co.getRecordset();
1201

    
1202
                                        ProjectExtension ext = (ProjectExtension) PluginServices.getExtension(ProjectExtension.class);
1203

    
1204
                                        ProjectTable projectTable = ext.getProject().getTable(co);
1205
                                        EditableAdapter ea=null;
1206
                                        ReadableVectorial rv=((FLyrVect)actives[i]).getSource();
1207
                                        if (rv instanceof VectorialEditableAdapter){
1208
                                                ea=(EditableAdapter)((FLyrVect)actives[i]).getSource();
1209
                                        }else{
1210
                                                ea=new EditableAdapter();
1211
                                                SelectableDataSource sds=((FLyrVect)actives[i]).getRecordset();
1212
                                                ea.setOriginalDataSource(sds);
1213
                                        }
1214

    
1215
                                        if (projectTable == null) {
1216
                                                projectTable = ProjectFactory.createTable(PluginServices.getText(this, "Tabla_de_Atributos") + ": " + actives[i].getName(),
1217
                                                                ea);
1218
                                                projectTable.setProjectDocumentFactory(new ProjectTableFactory());
1219
                                                projectTable.setAssociatedTable(co);
1220
                                                ext.getProject().addDocument(projectTable);
1221
                                        }
1222
                                        projectTable.setModel(ea);
1223
                                        
1224
                                        // Removed part of code that created another (visual) table
1225
//                                        Table t = new Table();
1226
//                                        t.setModel(projectTable);
1227
//                                        PluginServices.getMDIManager().addWindow(t);
1228
                                }
1229
                        }
1230
                } catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
1231
            NotificationManager.addError(PluginServices.getText(this,"No_se_pudo_obtener_la_tabla_de_la_capa"), e);
1232
        } catch (com.iver.cit.gvsig.fmap.DriverException e) {
1233
                        e.printStackTrace();
1234
                        NotificationManager.addError(PluginServices.getText(this,"No_se_pudo_obtener_la_tabla_de_la_capa"), e);
1235
        }
1236
        }
1237
        
1238
        ///// END UPDATE TABLES DATA /////
1239
        
1240
        ///// OTHER METHODS /////
1241
        
1242
        /**
1243
         * DOCUMENT ME!
1244
         *
1245
         * @param expresion DOCUMENT ME!
1246
         * @param substring DOCUMENT ME!
1247
         * @param startingPos DOCUMENT ME!
1248
         *
1249
         * @return DOCUMENT ME!
1250
         */
1251
        private int getIndex(String expresion, String substring, int startingPos) {
1252
                int index = startingPos;
1253

    
1254
                do {
1255
                        index = expresion.indexOf(substring, index);
1256
                } while ((StringUtilities.isBetweenSymbols(expresion, index, "\"")) &&
1257
                                (index != -1));
1258

    
1259
                return index;
1260
        }
1261
        
1262
        /**
1263
         * DOCUMENT ME!
1264
         *
1265
         * @param arg0
1266
         *
1267
         * @return
1268
         */
1269
        public boolean addExpressionListener(ExpressionListener arg0) {
1270
                return expressionListeners.add(arg0);
1271
        }
1272

    
1273
        /**
1274
         * DOCUMENT ME!
1275
         *
1276
         * @param arg0
1277
         *
1278
         * @return
1279
         */
1280
        public boolean removeExpressionListener(ExpressionListener arg0) {
1281
                return expressionListeners.remove(arg0);
1282
        }
1283
        /**
1284
         * DOCUMENT ME!
1285
         *
1286
         * @param o DOCUMENT ME!
1287
         *
1288
         * @return DOCUMENT ME!
1289
         */
1290
        public boolean removeExceptionListener(ExceptionListener o) {
1291
                return exceptionHandlingSupport.removeExceptionListener(o);
1292
        }
1293

    
1294
        /**
1295
         * DOCUMENT ME!
1296
         *
1297
         * @param t DOCUMENT ME!
1298
         */
1299
        private void throwException(Throwable t) {
1300
                exceptionHandlingSupport.throwException(t);
1301
        }
1302
        
1303
        ///// END OTHER METHODS ///// 
1304
}