Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.swing / org.gvsig.fmap.dal.swing.impl / src / main / java / org / gvsig / fmap / dal / swing / impl / searchpanel / SearchConditionFieldController.java @ 47361

History | View | Annotate | Download (73.6 KB)

1
package org.gvsig.fmap.dal.swing.impl.searchpanel;
2

    
3
import java.awt.Cursor;
4
import java.awt.Dimension;
5
import java.awt.event.ActionEvent;
6
import java.awt.event.ItemEvent;
7
import java.awt.event.ItemListener;
8
import java.awt.event.MouseAdapter;
9
import java.awt.event.MouseEvent;
10
import java.text.DateFormat;
11
import java.util.ArrayList;
12
import java.util.Arrays;
13
import java.util.Collections;
14
import java.util.Comparator;
15
import java.util.Date;
16
import java.util.HashMap;
17
import java.util.Iterator;
18
import java.util.List;
19
import java.util.Locale;
20
import java.util.Map;
21
import java.util.Objects;
22
import javax.json.JsonArray;
23
import javax.json.JsonObject;
24
import javax.swing.ComboBoxModel;
25
import javax.swing.DefaultComboBoxModel;
26
import javax.swing.ImageIcon;
27
import javax.swing.JButton;
28
import javax.swing.JComboBox;
29
import javax.swing.JLabel;
30
import javax.swing.JOptionPane;
31
import javax.swing.JTextField;
32
import javax.swing.SwingUtilities;
33
import javax.swing.text.JTextComponent;
34
import org.apache.commons.lang3.StringUtils;
35
import org.apache.commons.lang3.mutable.MutableBoolean;
36
import org.cresques.cts.IProjection;
37
import org.gvsig.expressionevaluator.ExpressionBuilder;
38
import org.gvsig.expressionevaluator.GeometryExpressionBuilder;
39
import org.gvsig.fmap.dal.DALLocator;
40
import org.gvsig.fmap.dal.DataManager;
41
import org.gvsig.fmap.dal.DataStore;
42
import org.gvsig.fmap.dal.DataTypes;
43
import org.gvsig.fmap.dal.SQLBuilder;
44
import org.gvsig.fmap.dal.StoresRepository;
45
import org.gvsig.fmap.dal.complements.Search;
46
import org.gvsig.fmap.dal.exception.DataException;
47
import org.gvsig.fmap.dal.expressionevaluator.DALExpressionBuilder;
48
import org.gvsig.fmap.dal.feature.Feature;
49
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
50
import org.gvsig.fmap.dal.feature.FeatureQuery;
51
import org.gvsig.fmap.dal.feature.FeatureReference;
52
import org.gvsig.fmap.dal.feature.FeatureSet;
53
import org.gvsig.fmap.dal.feature.FeatureStore;
54
import org.gvsig.fmap.dal.feature.FeatureType;
55
import org.gvsig.fmap.dal.feature.ForeingKey;
56
import org.gvsig.fmap.dal.swing.DALSwingLocator;
57
import org.gvsig.fmap.dal.swing.impl.featuretype.DefaultFeatureAttributeSelectionPanel;
58
import static org.gvsig.fmap.dal.swing.impl.searchpanel.SearchConditionPanelSimplified.PANEL_NAME;
59
import static org.gvsig.fmap.dal.swing.searchpanel.FeatureStoreSearchPanel.NOT_HANDLE_NULL;
60
import static org.gvsig.fmap.dal.swing.searchpanel.FeatureStoreSearchPanel.NULL_AS_FALSE;
61
import static org.gvsig.fmap.dal.swing.searchpanel.FeatureStoreSearchPanel.NULL_AS_TRUE;
62
import org.gvsig.fmap.dal.swing.searchpanel.SearchParameters;
63
import org.gvsig.fmap.geom.Geometry;
64
import org.gvsig.fmap.geom.GeometryUtils;
65
import org.gvsig.json.Json;
66
import org.gvsig.json.JsonArrayBuilder;
67
import org.gvsig.json.JsonObjectBuilder;
68
import org.gvsig.tools.ToolsLocator;
69
import org.gvsig.tools.dataTypes.Coercion;
70
import org.gvsig.tools.dataTypes.CoercionException;
71
import org.gvsig.tools.dataTypes.DataTypeUtils;
72
import org.gvsig.tools.dispose.DisposeUtils;
73
import org.gvsig.tools.dynobject.DynField;
74
import org.gvsig.tools.i18n.I18nManager;
75
import org.gvsig.tools.swing.api.DropDown;
76
import org.gvsig.tools.swing.api.ToolsSwingLocator;
77
import org.gvsig.tools.swing.api.ToolsSwingManager;
78
import org.gvsig.tools.swing.api.pickercontroller.DatePickerController;
79
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
80
import org.gvsig.tools.swing.api.windowmanager.Dialog;
81
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
82
import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2;
83
import org.gvsig.tools.swing.icontheme.IconTheme;
84
import org.gvsig.tools.task.CancellableTask;
85
import org.gvsig.tools.util.CompareUtils;
86
import org.gvsig.tools.util.LabeledValue;
87
import org.gvsig.tools.util.LabeledValueImpl;
88
import org.gvsig.tools.visitor.VisitCanceledException;
89
import org.slf4j.Logger;
90
import org.slf4j.LoggerFactory;
91

    
92
/**
93
 *
94
 * @author jjdelcerro
95
 */
96
@SuppressWarnings("UseSpecificCatch")
97
public class SearchConditionFieldController {
98

    
99
    private static final Logger LOGGER = LoggerFactory.getLogger(SearchConditionFieldController.class);
100
    private static final Class LOAD_MORE_ELEMENTS = SearchConditionFieldController.class;
101

    
102
    private static final int MAXLEN_IN_COMBOS = 70;
103
    
104
    /*friend*/ static final int GEOM_OPERAND_MODE_EMPTY = 0;
105
    /*friend*/ static final int GEOM_OPERAND_MODE_CLIPBOARD = 1;
106
    /*friend*/ static final int GEOM_OPERAND_MODE_LAYER_SELECTION = 2;
107
    /*friend*/ static final int GEOM_OPERAND_MODE_CONSTANT = 3;
108
    
109
    private static final String OPERATOR_CONTAINS = "CONTAINS";
110

    
111
    private class UpdateValueList implements Runnable, CancellableTask {
112

    
113
        private final Field field;
114
        private boolean cancelled;
115

    
116
        public UpdateValueList(Field field) {
117
            this.field = field;
118
        }
119
        
120
        @Override
121
        public void run() {
122
            if (isCancellationRequested()) {
123
                return;
124
            }
125
            final FeatureStore theStore = field.getFeatureStore();
126
            final FeatureQuery query;
127
            query = theStore.createFeatureQuery();
128
            query.addAttributeName(field.getDescriptor().getName());
129
            query.setFilter("");
130
    //        query.getExtraColumns().copyFrom(this.parameters.getQuery().getExtraColumns());
131
            query.setLimit(updateValuesFeaturesLimit);
132
            query.getGroupByColumns().clear();
133
            query.getAggregateFunctions().clear();     
134
            
135
            FeatureSet set = null;
136
            final List<Object> values = new ArrayList<>();
137
            final DefaultComboBoxModel model = new DefaultComboBoxModel();
138
            MutableBoolean canHasMoreElements = new MutableBoolean();
139
            
140
            try {
141
                canHasMoreElements.setFalse();
142
                if (isCancellationRequested()) {
143
                    return;
144
                }
145
                set = theStore.getFeatureSet(query);
146
                if (set.size() >= updateValuesFeaturesLimit) {
147
                    canHasMoreElements.setTrue();
148
                }
149
                final long timeLimit = System.currentTimeMillis() + updateValuesTimeLimit * 1000;
150
                set.accept((Object o) -> {
151
                    if (isCancellationRequested()) {
152
                        throw new VisitCanceledException();
153
                    }
154
                    Object value = ((Feature) o).get(field.getDescriptor().getName());
155
                    if (value != null && !values.contains(value)) {
156
                        values.add(value);
157
                    }
158
                    if (System.currentTimeMillis() > timeLimit) {
159
                        canHasMoreElements.setTrue();
160
                        throw new VisitCanceledException();
161
                    }
162
                    if (values.size() > updateValuesFeaturesLimit) {
163
                        canHasMoreElements.setTrue();
164
                        throw new VisitCanceledException();
165
                    }
166
                });
167
            } catch (VisitCanceledException ex) {
168
                canHasMoreElements.setTrue();
169
            } catch (Exception ex) {
170
                canHasMoreElements.setFalse();
171
                LOGGER.warn("Can't update list of values of '" + field.getLabel() + "'.", ex);
172
            } finally {
173
                DisposeUtils.disposeQuietly(set);
174
            }
175
            if (isCancellationRequested()) {
176
                return;
177
            }
178
            List<LabeledValue> elements = new ArrayList<>();
179
            if (!values.isEmpty()) {
180
                LabeledValue[] availableValues = field.getDescriptor().getAvailableValues();
181
                Map<String, String> availableValuesMap = new HashMap<>();
182
                if (availableValues != null) {
183
                    for (LabeledValue availableValue : availableValues) {
184
                        availableValuesMap.put(
185
                                Objects.toString(availableValue.getValue()),
186
                                availableValue.getLabel()
187
                        );
188
                    }
189
                }
190
                elements.add(new LabeledValueImpl("", null, MAXLEN_IN_COMBOS));
191
                for (Object value : values) {
192
                    String key;
193
                    key = DataTypeUtils.toString(value);
194
                    String label = availableValuesMap.getOrDefault(key, key);
195
                    elements.add(new LabeledValueImpl(label, value, MAXLEN_IN_COMBOS));
196
                }
197
                Comparator comparator = null;
198
                if (availableValues == null) {
199
                    switch (field.getDescriptor().getType()) {
200
                        case DataTypes.DATE:
201
                        case DataTypes.TIME:
202
                        case DataTypes.TIMESTAMP:
203
                            comparator = new CompareUtils.NullSafeComparator() {
204
                                @Override
205
                                public int safeCompare(Object o1, Object o2) {
206
                                    Comparable v1 = (Comparable) ((LabeledValue) o1).getValue();
207
                                    Comparable v2 = (Comparable) ((LabeledValue) o2).getValue();
208
                                    if (v1 == v2) {
209
                                        return 0;
210
                                    }
211
                                    if (v1 == null) {
212
                                        return -1;
213
                                    }
214
                                    if (v2 == null) {
215
                                        return 1;
216
                                    }
217
                                    return v1.compareTo(v2);
218
                                }
219
                            };
220
                    }
221
                }
222
                elements.sort(comparator);
223

    
224
            }
225
            for (LabeledValue element : elements) {
226
                model.addElement(element);
227
            }
228
            if (canHasMoreElements.isTrue()) {
229
                model.addElement(new LabeledValueImpl("...", LOAD_MORE_ELEMENTS));
230
            }
231
            if (isCancellationRequested()) {
232
                return;
233
            }
234
            SwingUtilities.invokeLater(new Runnable() {
235
                @Override
236
                public void run() {
237
                    if (isCancellationRequested()) {
238
                        return;
239
                    }
240
                    setEnabled(false);
241
                    Dimension sz = cboValue.getPreferredSize();
242
                    cboValue.setModel(model);
243
                    cboValue.setPreferredSize(sz);
244
                    if (valueAssigned != null) {
245
                        cboValue.setSelectedItem(valueAssigned);
246
                        valueAssigned = null;
247
                    }
248
                    setEnabled(true);
249
                }
250
            });
251
        }
252

    
253
        @Override
254
        public boolean isCancellationRequested() {
255
            return this.cancelled;
256
        }
257

    
258
        @Override
259
        public void cancelRequest() {
260
            this.cancelled = true;
261
        }
262
        
263
    }
264
    
265
    private static class Field extends LabeledValueImpl<String> {
266

    
267
        FeatureAttributeDescriptor attrdesc;
268
        private final FeatureStore store;
269
        private final int presentationMode;
270
        private final boolean showStoreName;
271
        private final FeatureAttributeDescriptor[] path;
272

    
273
        public Field(FeatureAttributeDescriptor[] path, FeatureStore store, FeatureAttributeDescriptor attrdesc, int presentationMode) {
274
            this(path, store, attrdesc, presentationMode, false);
275
        }
276

    
277
        public Field(
278
                FeatureAttributeDescriptor[] path,
279
                FeatureStore store,
280
                FeatureAttributeDescriptor attrdesc,
281
                int presentationMode,
282
                boolean showStoreName
283
        ) {
284
            super(
285
                    DALSwingLocator.getDataSwingManager().getAttributeDescriptorLabel(attrdesc, store.getName()),
286
                    attrdesc.getName()
287
            );
288
            this.path = path;
289
            this.store = store;
290
            this.attrdesc = attrdesc;
291
            this.presentationMode = presentationMode;
292
            this.showStoreName = showStoreName;
293
        }
294

    
295
        public FeatureAttributeDescriptor[] getPath() {
296
            return this.path;
297
        }
298

    
299
        @Override
300
        public String getLabel() {
301
            String theLabel = DALSwingLocator.getDataSwingManager().getAttributeDescriptorLabel(attrdesc, showStoreName ? store.getName() : null);
302
            switch (this.presentationMode) {
303
                case Search.OrderedAttribute.TYPE_REGURAL:
304
                    break;
305
                case Search.OrderedAttribute.TYPE_FAVORITE:
306
                    theLabel = "<html><b>" + theLabel + "</b></html>";
307
                    break;
308
                case Search.OrderedAttribute.TYPE_RECENT:
309
                    theLabel = "<html><i><b>" + theLabel + "</b></i></html>";
310
                    break;
311
            }
312
            return theLabel;
313
        }
314

    
315
        public FeatureAttributeDescriptor getParentDescriptor() {
316
            int l = this.path.length;
317
            if (l < 2) {
318
                return null;
319
            }
320
            return this.path[l - 2];
321
        }
322

    
323
        public FeatureAttributeDescriptor getDescriptor() {
324
            return this.attrdesc;
325
        }
326

    
327
        public FeatureStore getFeatureStore() {
328
            return this.store;
329
        }
330

    
331
    }
332

    
333
    private FeatureStore store;
334
    private SearchParameters parameters;
335
    private final JLabel lblFields;
336
    private final JLabel lblExtraFields;
337
    private final JLabel lblLogicalOperators;
338
    private final JLabel lblRelationalOperators;
339
    private final JComboBox cboValue;
340
    private final JTextField txtValue;
341
    private final JButton btnValue;
342
    private final JLabel lblNull;
343
    private Object valueAssigned = null;
344

    
345
    private DropDown ddnFields;
346
    private DropDown ddnLogicalOperators;
347
    private DropDown ddnRelationalOperators;
348
    private DropDown ddnNullBehavior;
349

    
350
    private LabeledValue[] relationalOperators;
351
    private LabeledValue[] logicalOperators;
352
    private LabeledValue[] nullBehaviors;
353
    private ArrayList<ImageIcon> nullOperatorsIcons;
354

    
355
    private final int SIZE_ORDERED_ATTRIBUTES = 20;
356
    private DatePickerController dateController = null;
357

    
358
    private int updateValuesTimeLimit;
359
    private int updateValuesFeaturesLimit;
360

    
361
    private UpdateValueList updateValueListTask;
362
    private LabeledValue[] geometryRelationalOperators;
363
    private DefaultComboBoxModel modelRelationalOperators;
364
    private DefaultComboBoxModel modelGeometryRelationalOperators;
365
    
366
    private int geometryOperandMode;
367
    private String geometryOperandStoreName;
368
    private Geometry geometryOperandConstant;
369
    
370
    public SearchConditionFieldController(
371
            SearchParameters parameters,
372
            FeatureStore store,
373
            SearchConditionFieldView view           
374
    ) {
375
        this.parameters = parameters;
376
        this.store = store;
377
        this.lblFields = view.lblFields;
378
        this.lblExtraFields = view.lblExtraFields;
379
        this.lblRelationalOperators = view.lblRelationalOperators;
380
        this.cboValue = view.cboValue;
381
        this.txtValue = view.txtValue;
382
        this.btnValue = view.btnValue;
383
        this.lblNull = view.lblNull;
384
        this.lblLogicalOperators = view.lblLogicalOperators;
385
        this.updateValuesTimeLimit = 60;
386
        this.updateValuesFeaturesLimit = 1000;
387
        this.initComponents();
388
    }
389

    
390
    public boolean isAValidRelationOperator(String name) {
391
        for (LabeledValue relationalOperator : relationalOperators) {
392
            if (StringUtils.equalsIgnoreCase(name, (CharSequence) relationalOperator.getValue())) {
393
                return true;
394
            }
395
        }
396
        return false;
397
    }
398

    
399
    @SuppressWarnings("Convert2Lambda")
400
    private void initComponents() {
401
        try {
402
            I18nManager i18n = ToolsLocator.getI18nManager();
403
            ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
404

    
405
            relationalOperators = new LabeledValue[]{
406
                new LabeledValueImpl(i18n.getTranslation("_Contains"), OPERATOR_CONTAINS),
407
                new LabeledValueImpl(i18n.getTranslation("_Equals_to"), ExpressionBuilder.OPERATOR_EQ),
408
                new LabeledValueImpl(i18n.getTranslation("_Like_to"), ExpressionBuilder.OPERATOR_ILIKE),
409
                new LabeledValueImpl(i18n.getTranslation("_Not_equals_to"), ExpressionBuilder.OPERATOR_NE),
410
                new LabeledValueImpl(i18n.getTranslation("_Greater_than"), ExpressionBuilder.OPERATOR_GT),
411
                new LabeledValueImpl(i18n.getTranslation("_Greater_or_equal_to"), ExpressionBuilder.OPERATOR_GE),
412
                new LabeledValueImpl(i18n.getTranslation("_Less_than"), ExpressionBuilder.OPERATOR_LT),
413
                new LabeledValueImpl(i18n.getTranslation("_Less_or_equal_to"), ExpressionBuilder.OPERATOR_LE),
414
                new LabeledValueImpl(i18n.getTranslation("_Is_null"), ExpressionBuilder.OPERATOR_IS_NULL),
415
                new LabeledValueImpl(i18n.getTranslation("_Is_not_null"), ExpressionBuilder.OPERATOR_IS_NOT_NULL)
416
            };
417

    
418
            this.geometryRelationalOperators = new LabeledValue[]{
419
                new LabeledValueImpl(i18n.getTranslation("_Is_covered_by"), GeometryExpressionBuilder.FUNCTION_ST_COVEREDBY),
420
                new LabeledValueImpl(i18n.getTranslation("_Covers_to"), GeometryExpressionBuilder.FUNCTION_ST_COVERS),
421
                new LabeledValueImpl(i18n.getTranslation("_Contains_to"), GeometryExpressionBuilder.FUNCTION_ST_CONTAINS),
422
                new LabeledValueImpl(i18n.getTranslation("_Crosses_to"), GeometryExpressionBuilder.FUNCTION_ST_CROSSES),
423
                new LabeledValueImpl(i18n.getTranslation("_Is_disjoint_with"), GeometryExpressionBuilder.FUNCTION_ST_DISJOINT),
424
                new LabeledValueImpl(i18n.getTranslation("_Intersects_with"), GeometryExpressionBuilder.FUNCTION_ST_INTERSECTS),
425
//                new LabeledValueImpl(i18n.getTranslation("_Is_closed"), GeometryExpressionBuilder.FUNCTION_ST_ISCLOSED),
426
                new LabeledValueImpl(i18n.getTranslation("_Overlaps_with"), GeometryExpressionBuilder.FUNCTION_ST_OVERLAPS),
427
                new LabeledValueImpl(i18n.getTranslation("_Touches_with"), GeometryExpressionBuilder.FUNCTION_ST_TOUCHES),
428
                new LabeledValueImpl(i18n.getTranslation("_Is_within_of"), GeometryExpressionBuilder.FUNCTION_ST_WITHIN),
429
                new LabeledValueImpl(i18n.getTranslation("_Is_equals_to"), GeometryExpressionBuilder.FUNCTION_ST_EQUALS),
430
                new LabeledValueImpl(i18n.getTranslation("_Is_null"), ExpressionBuilder.OPERATOR_IS_NULL),
431
                new LabeledValueImpl(i18n.getTranslation("_Is_not_null"), ExpressionBuilder.OPERATOR_IS_NOT_NULL)
432
            };
433

    
434
            logicalOperators = new LabeledValue[]{
435
                new LabeledValueImpl(i18n.getTranslation("_Or"), ExpressionBuilder.OPERATOR_OR),
436
                new LabeledValueImpl(i18n.getTranslation("_And"), ExpressionBuilder.OPERATOR_AND)
437
            };
438

    
439
            nullBehaviors = new LabeledValue[]{
440
                new LabeledValueImpl(i18n.getTranslation("_Not_handle_null_values"), NOT_HANDLE_NULL),
441
                new LabeledValueImpl(i18n.getTranslation("_Null_values_as_true"), NULL_AS_TRUE),
442
                new LabeledValueImpl(i18n.getTranslation("_Null_values_as_false"), NULL_AS_FALSE)
443
            };
444

    
445
            nullOperatorsIcons = new ArrayList<ImageIcon>();
446
            nullOperatorsIcons.add(ToolsSwingLocator.getIconThemeManager().getCurrent().get("search-nullbehavior-null"));
447
            nullOperatorsIcons.add(ToolsSwingLocator.getIconThemeManager().getCurrent().get("search-nullbehavior-true"));
448
            nullOperatorsIcons.add(ToolsSwingLocator.getIconThemeManager().getCurrent().get("search-nullbehavior-false"));
449

    
450
            this.lblExtraFields.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
451

    
452
            this.ddnFields = toolsSwingManager.createDropDown(lblFields);
453
            this.ddnFields.setVisibleDropdownArrow(false);
454
            this.ddnRelationalOperators = toolsSwingManager.createDropDown(lblRelationalOperators);
455
            this.ddnRelationalOperators.setVisibleDropdownArrow(false);
456
            if (lblLogicalOperators != null) {
457
                this.ddnLogicalOperators = toolsSwingManager.createDropDown(lblLogicalOperators);
458
                this.ddnLogicalOperators.setVisibleDropdownArrow(false);
459
            }
460

    
461
            this.modelRelationalOperators = new DefaultComboBoxModel();
462
            for (LabeledValue op : relationalOperators) {
463
                modelRelationalOperators.addElement(op);
464
            }
465
            this.modelGeometryRelationalOperators = new DefaultComboBoxModel();
466
            for (LabeledValue op : geometryRelationalOperators) {
467
                modelGeometryRelationalOperators.addElement(op);
468
            }
469
            this.ddnRelationalOperators.setModel(modelRelationalOperators);
470
            this.ddnRelationalOperators.addItemListener(new ItemListener() {
471
                @Override
472
                public void itemStateChanged(ItemEvent ie) {
473
                    doUpdateControllerByRelationalOperator();
474
                }
475
            });
476

    
477
            if (this.ddnLogicalOperators != null) {
478
                DefaultComboBoxModel modelLogicalOperators = new DefaultComboBoxModel();
479
                for (LabeledValue op : logicalOperators) {
480
                    modelLogicalOperators.addElement(op);
481
                }
482
                this.ddnLogicalOperators.setModel(modelLogicalOperators);
483
                this.ddnLogicalOperators.setSelectedIndex(1);
484
            }
485

    
486
            this.ddnNullBehavior = toolsSwingManager.createDropDownIcon(lblNull);
487
            this.ddnNullBehavior.setVisibleDropdownArrow(false);
488
            DefaultComboBoxModel modelNullOperators = new DefaultComboBoxModel();
489
            for (LabeledValue op : nullBehaviors) {
490
                modelNullOperators.addElement(op);
491
            }
492
            this.ddnNullBehavior.setModel(modelNullOperators);
493
            this.ddnNullBehavior.setIcons(nullOperatorsIcons);
494
            this.ddnNullBehavior.setSelectedIndex(0);
495
            FeatureType featureType = parameters.getFeatureType(store);
496
            Search search = (Search) ToolsLocator.getComplementsManager().get(
497
                    Search.COMPLEMENT_MANE, featureType
498
            );
499
            List<Search.OrderedAttribute> orderedAttributes = search.getOrderedAttributes(
500
//                    Search.BASIC_TYPES_FILTER,
501
                    Search.BASIC_TYPES_FILTER
502
                        .or((FeatureAttributeDescriptor t) -> t.getType()==DataTypes.GEOMETRY),
503
                    Search.STR_INT_LONG_LABEL_ORDER,
504
                    SIZE_ORDERED_ATTRIBUTES
505
            );
506
            List<ImageIcon> icons = new ArrayList<>();
507
//            DataTypesManager dataTypeManager = ToolsLocator.getDataTypesManager();
508
            IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getCurrent();
509
            DefaultComboBoxModel model = new DefaultComboBoxModel();
510
            for (Search.OrderedAttribute attr : orderedAttributes) {
511
                FeatureAttributeDescriptor attrdesc = attr.getDescriptor();
512
                Field field = new Field(
513
                        new FeatureAttributeDescriptor[]{attrdesc},
514
                        this.store,
515
                        attrdesc,
516
                        attr.getType()
517
                );
518
                model.addElement(field);
519
                String iconName = attrdesc.getDataType().getIconName();
520
                if (iconTheme.exists(iconName)) {
521
                    icons.add(iconTheme.get(iconName));
522
                } else {
523
                    icons.add(null);
524
                }
525
            }
526

    
527
            this.ddnFields.setIcons(icons);
528
            this.ddnFields.setModel(model);
529
            this.ddnFields.addItemListener(new ItemListener() {
530
                @Override
531
                public void itemStateChanged(ItemEvent e) {
532
                    if (e.getStateChange() == ItemEvent.SELECTED) {
533
                        doUpdateValuesList();
534
                    }
535

    
536
                }
537
            });
538

    
539
            this.cboValue.addItemListener(new ItemListener() {
540
                @Override
541
                public void itemStateChanged(ItemEvent e) {
542
                    if (e.getStateChange() == ItemEvent.SELECTED) {
543
                        if (cboValue.getSelectedItem() != null && cboValue.getSelectedItem() instanceof LabeledValue) {
544
                            if (Objects.equals(((LabeledValue) cboValue.getSelectedItem()).getValue(), LOAD_MORE_ELEMENTS)) {
545
                                setUpdateValuesLimits(updateValuesTimeLimit + 10, updateValuesFeaturesLimit + 1000);
546
                            }
547
                        }
548
                    }
549
                }
550
            });
551

    
552
            this.lblExtraFields.addMouseListener(new MouseAdapter() {
553
                @Override
554
                public void mouseClicked(MouseEvent e) {
555
                    doSelectMoreFields();
556
                }
557
            });
558
            this.txtValue.setVisible(false);
559
            this.btnValue.setVisible(false);
560
            this.geometryOperandMode = GEOM_OPERAND_MODE_EMPTY;
561
            this.geometryOperandStoreName = null;
562
            this.geometryOperandConstant = null;
563
            this.btnValue.addActionListener((ActionEvent e) -> {doSelectGeometryOperand(); });
564

    
565
            doUpdateControllerByRelationalOperator();
566
//      clear();
567
        } catch (Exception ex) {
568
            throw new RuntimeException(ex);
569
        }
570
    }
571

    
572
    private void doUpdateControllerByRelationalOperator() {
573
        Object item = ((LabeledValue) ddnRelationalOperators.getSelectedItem()).getValue();
574
        if (ExpressionBuilder.OPERATOR_IS_NULL.equals(item) || ExpressionBuilder.OPERATOR_IS_NOT_NULL.equals(item)) {
575
            lblNull.setEnabled(false);
576
            cboValue.setEnabled(false);
577
            cboValue.setSelectedIndex(-1);
578
        } else {
579
            lblNull.setEnabled(true);
580
            cboValue.setEnabled(true);
581
        }
582
        doUpdateCurrentValue();
583
    }
584

    
585
    private void doUpdateCurrentValue() {
586
        Field field = this.getCurrentField();
587
        if( field!=null ) {
588
            FeatureAttributeDescriptor desc = field.getDescriptor();
589
            int type = desc==null? DataTypes.INT:desc.getType();
590
            switch(type) {
591
                case DataTypes.GEOMETRY:
592
                    this.cboValue.setVisible(false);
593
                    this.txtValue.setVisible(true);
594
                    this.btnValue.setVisible(true);
595
                    switch(this.geometryOperandMode) {
596
                        case GEOM_OPERAND_MODE_CONSTANT:
597
                            if( this.geometryOperandConstant == null ) {
598
                                this.txtValue.setText("");
599
                            } else {
600
                                this.txtValue.setText(Objects.toString(GeometryUtils.toWKT(this.geometryOperandConstant), ""));
601
                            }
602
                            break;
603
                        case GEOM_OPERAND_MODE_LAYER_SELECTION:
604
                            if( this.geometryOperandStoreName!=null ) {
605
                                StoresRepository repo = DALLocator.getDataManager().getStoresRepository();
606
                                this.txtValue.setText(repo.getLabelOrName(this.geometryOperandStoreName));
607
                                break;
608
                            }
609
                            this.geometryOperandMode = GEOM_OPERAND_MODE_CLIPBOARD;
610
                        case GEOM_OPERAND_MODE_CLIPBOARD:
611
                            this.txtValue.setText("Contenido del portapapeles"); // i18n.getTranslation("_Clipboard_content"));
612
                            break;
613
                    }
614
                    break;
615
                default:
616
                    if( this.txtValue.isVisible() ) {
617
                        this.ddnRelationalOperators.setSelectedIndex(1);
618
                    }
619
                    this.cboValue.setVisible(true);
620
                    this.txtValue.setVisible(false);
621
                    this.btnValue.setVisible(false);
622
            }
623
        }
624
    }
625

    
626
    private FeatureType getFeatureType() {
627
        try {
628
            return this.store.getDefaultFeatureType();
629
        } catch (DataException ex) {
630
            return null;
631
        }
632
    }
633

    
634
    private void doSelectMoreFields() {
635
        DefaultFeatureAttributeSelectionPanel panel = new DefaultFeatureAttributeSelectionPanel(
636
                store, 
637
                parameters.getFeatureType(store),
638
                parameters.getQuery()
639
        );
640
        WindowManager_v2 winManager = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
641
        final Dialog dialog = winManager.createDialog(
642
                panel,
643
                "Select attribute",
644
                null,
645
                WindowManager_v2.BUTTONS_OK_CANCEL
646
        );
647
        dialog.addActionListener((ActionEvent e) -> {
648
            if (dialog.getAction() == WindowManager_v2.BUTTONS_OK) {
649
                doAddAndSelect(
650
                        panel.getSelectedStore(),
651
                        panel.getSelectedAttributeDescriptor(),
652
                        panel.getSelectedPath()
653
                );
654
            }
655
        });
656
        dialog.show(WindowManager.MODE.DIALOG);
657

    
658
    }
659

    
660
    private void doAddAndSelect(FeatureStore theStore, FeatureAttributeDescriptor attrdesc, FeatureAttributeDescriptor[] path) {
661
        ThreadSafeDialogsManager dialogManager = ToolsSwingLocator.getThreadSafeDialogsManager();
662
        I18nManager i18n = ToolsLocator.getI18nManager();
663
        DefaultComboBoxModel<Field> model = (DefaultComboBoxModel) this.ddnFields.getModel();
664
        if (attrdesc == null) {
665
            dialogManager.messageDialog(
666
                    i18n.getTranslation("_It_is_not_supported_to_search_through_this_field") + "\n"
667
                    + i18n.getTranslation("_Field_not_found"),
668
                    "_Warning",
669
                    JOptionPane.WARNING_MESSAGE
670
            );
671
            return;
672
        }
673

    
674
        for (int i = 0; i < model.getSize(); i++) {
675
            Field field = model.getElementAt(i);
676
            FeatureAttributeDescriptor attrdescN = field.getDescriptor();
677
            if (theStore!=null && attrdescN.getStore()!=null && isTheSameStore(theStore, attrdescN.getStore())
678
                    && StringUtils.equalsIgnoreCase(attrdesc.getName(), attrdescN.getName())) {
679
                this.setAttribute(i);
680
                return;
681
            }
682
        }
683
        Field field = new Field(
684
                path,
685
                theStore,
686
                attrdesc,
687
                Search.OrderedAttribute.TYPE_REGURAL,
688
                !isTheSameStore(store, theStore)
689
        );
690
        if (field.getPath().length > 2) {
691
            dialogManager.messageDialog(
692
                    i18n.getTranslation("_It_is_not_supported_to_search_through_this_field") + "\n"
693
                    + i18n.getTranslation("_To_many_links"),
694
                    "_Warning",
695
                    JOptionPane.WARNING_MESSAGE
696
            );
697
            return;
698
        }
699
        FeatureAttributeDescriptor parentDescriptor = field.getParentDescriptor();
700
        if (parentDescriptor != null) {
701
            switch (parentDescriptor.getRelationType()) {
702
                case DynField.RELATION_TYPE_AGGREGATE:
703
                case DynField.RELATION_TYPE_COMPOSITION:
704
                    if (getForeingKeyName(field.getFeatureStore(), this.store) == null) {
705
                        dialogManager.messageDialog(
706
                                "It not supported to search through this field." + "\n"
707
                                + "The link field was not found.",
708
                                "_Warning",
709
                                JOptionPane.WARNING_MESSAGE
710
                        );
711
                        return;
712
                    }
713
                    if (getPrimaryKeyName(this.store) == null) {
714
                        dialogManager.messageDialog(
715
                                "It not supported to search through this field." + "\n"
716
                                + "A simple primary key was not found.",
717
                                "_Warning",
718
                                JOptionPane.WARNING_MESSAGE
719
                        );
720
                        return;
721
                    }
722
            }
723
        }
724
        model.addElement(field);
725
        IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getCurrent();
726
        this.ddnFields.getIcons().add(iconTheme.get(attrdesc.getDataType().getIconName()));
727
        this.setAttribute(model.getSize() - 1);
728
    }
729

    
730
    public void clear() {
731
        this.ddnRelationalOperators.setSelectedIndex(0);
732
        if (this.ddnLogicalOperators != null) {
733
            this.ddnLogicalOperators.setSelectedIndex(1);
734
        }
735
        this.cboValue.setSelectedIndex(-1);
736
        this.ddnNullBehavior.setSelectedIndex(0);
737
        this.geometryOperandStoreName = null;
738
        this.geometryOperandMode = GEOM_OPERAND_MODE_EMPTY;
739
        doUpdateControllerByRelationalOperator();
740
    }
741

    
742
    private String lastNameInUpdateValuesList = null;
743
    private int lastUpdateValuesFeaturesLimit = -1;
744
    private int lastUpdateValuesTimeLimit = -1;
745
    
746
    private void doUpdateValuesList() {
747
        final Field field = (Field) this.ddnFields.getSelectedItem();
748
        if (field == null) {
749
            return;
750
        }
751
        FeatureAttributeDescriptor descriptor = field.getDescriptor();
752
        if(StringUtils.equalsIgnoreCase(lastNameInUpdateValuesList, descriptor.getName()) && 
753
                updateValuesFeaturesLimit == lastUpdateValuesFeaturesLimit && 
754
                updateValuesTimeLimit == lastUpdateValuesTimeLimit
755
                ){
756
            return;
757
        }
758
        lastNameInUpdateValuesList = descriptor.getName();
759
        lastUpdateValuesFeaturesLimit = updateValuesFeaturesLimit;
760
        lastUpdateValuesTimeLimit = updateValuesTimeLimit;
761
        
762
        if(this.updateValueListTask != null){
763
            this.updateValueListTask.cancelRequest();
764
        }
765
        Thread updateTask;
766
        switch(descriptor.getType()) {
767
            case DataTypes.GEOMETRY:
768
                this.ddnRelationalOperators.setModel(modelGeometryRelationalOperators);
769
                if( !this.txtValue.isVisible() ) {
770
                    this.ddnRelationalOperators.setSelectedIndex(0);
771
                }
772
                this.cboValue.setVisible(false);
773
                this.txtValue.setVisible(true);
774
                this.btnValue.setVisible(true);
775
                break;
776
            case DataTypes.DATE:
777
                if (this.dateController == null) {
778
                    this.dateController = ToolsSwingLocator.getToolsSwingManager().createDatePickerController(
779
                            (JTextComponent) this.cboValue.getEditor().getEditorComponent(),
780
                            null
781
                    );
782
                }
783
                this.ddnRelationalOperators.setModel(modelRelationalOperators);
784
                if( this.txtValue.isVisible() ) {
785
                    this.ddnRelationalOperators.setSelectedIndex(0);
786
                }
787
                this.cboValue.setVisible(true);
788
                this.txtValue.setVisible(false);
789
                this.btnValue.setVisible(false);
790
                this.updateValueListTask = new UpdateValueList(field);
791
                updateTask = new Thread(updateValueListTask);
792
                updateTask.start();
793
                break;
794
            default:
795
                this.ddnRelationalOperators.setModel(modelRelationalOperators);
796
                if( this.txtValue.isVisible() ) {
797
                    this.ddnRelationalOperators.setSelectedIndex(0);
798
                }
799
                this.cboValue.setVisible(true);
800
                this.txtValue.setVisible(false);
801
                this.btnValue.setVisible(false);
802
                if (this.dateController != null) {
803
                    this.dateController.uninstall();
804
                    this.dateController = null;
805
                }
806
                this.updateValueListTask = new UpdateValueList(field);
807
                updateTask = new Thread(updateValueListTask);
808
                updateTask.start();
809
        }
810
    }
811

    
812
    public void setEnabled(boolean enabled) {
813
        ddnFields.setEnabled(enabled);
814
        if (ddnLogicalOperators != null) {
815
            ddnLogicalOperators.setEnabled(enabled);
816
        }
817
        ddnRelationalOperators.setEnabled(enabled);
818
        lblExtraFields.setEnabled(enabled);
819
        cboValue.setEnabled(enabled);
820
        doUpdateControllerByRelationalOperator();
821
    }
822

    
823
    public String getRelationalOperator() {
824
        LabeledValue<String> op = (LabeledValue) this.ddnRelationalOperators.getSelectedItem();
825
        if (op == null) {
826
            return null;
827
        }
828
        return op.getValue();
829
    }
830

    
831
    public int setRelationalOperator(String name) {
832
        int n = 0;
833
        for (LabeledValue relationalOperator : relationalOperators) {
834
            if (StringUtils.equalsIgnoreCase(name, (CharSequence) relationalOperator.getValue())) {
835
                break;
836
            }
837
            n++;
838
        }
839
        if (this.relationalOperators.length <= n) {
840
            return -1;
841
        }
842
        this.ddnRelationalOperators.setSelectedIndex(n);
843
        doUpdateControllerByRelationalOperator();
844
        return n;
845
    }
846

    
847
    public String getLogicalOperator() {
848
        if (this.ddnLogicalOperators == null) {
849
            return null;
850
        }
851
        LabeledValue<String> rel = (LabeledValue) this.ddnLogicalOperators.getSelectedItem();
852
        if (rel == null) {
853
            return null;
854
        }
855
        return rel.getValue();
856
    }
857

    
858
    public void setLogicalOperator(String operator) {
859
        if (this.ddnLogicalOperators == null) {
860
            return;
861
        }
862
        ComboBoxModel model = this.ddnLogicalOperators.getModel();
863
        for (int i = 0; i < model.getSize(); i++) {
864
            LabeledValue modelValue = (LabeledValue) model.getElementAt(i);
865
            String value = (String) modelValue.getValue();
866
            if (StringUtils.equals(value, operator)) {
867
                this.ddnLogicalOperators.setSelectedIndex(i);
868
                break;
869
            }
870
        }
871
    }
872
    
873
    public Object getValue() {
874
        return this.getValue(true);
875
    }
876

    
877
    public Object getValue(boolean coerce) {
878
        final Field field = (Field) this.ddnFields.getSelectedItem();
879
        if (field == null) {
880
            return null;
881
        }
882
        Object v;
883
        if (this.dateController == null) {
884
            v = this.cboValue.getSelectedItem();
885
        } else {
886
            if(this.dateController.isValid()) {
887
                v = this.dateController.get();
888
            } else {
889
                v = null;
890
            }
891
        }
892
        if (v == null) {
893
            return null;
894
        }
895
        if (v instanceof LabeledValue) {
896
            v = ((LabeledValue) v).getValue();
897
            if (v == null || v == LOAD_MORE_ELEMENTS) {
898
                return null;
899
            }
900
        }
901
        if (v instanceof CharSequence) {
902
            if (StringUtils.isBlank((CharSequence) v)) {
903
                return null;
904
            }
905
        }
906
        if( coerce ) {
907
            Coercion coercion = field.getDescriptor().getDataType().getCoercion();
908
            try {
909
                return coercion.coerce(v);
910
            } catch (CoercionException ex) {
911
                return null;
912
            }
913
        }
914
        return v;
915
        
916
    }
917

    
918
    public void setValue(Object value) {
919
        //this.cboValue.setSelectedItem(value);
920
        SwingUtilities.invokeLater(new Runnable() {
921
            @Override
922
            public void run() {
923
                DefaultComboBoxModel model = (DefaultComboBoxModel) cboValue.getModel();
924
                for (int i = 0; i < model.getSize(); i++) {
925
                    Object item = model.getElementAt(i);
926
                    if (item.equals(value)) {
927
                        cboValue.setSelectedIndex(i);
928
                        valueAssigned = value;
929
                        return;
930
                    }
931
                }
932
                // si no lo encuentra en el modelo lo a?ade
933
                final Field field = (Field) ddnFields.getSelectedItem();
934
                if (field != null) {
935
                    LabeledValue[] availableValues = field.getDescriptor().getAvailableValues();
936
                    Map<String, String> availableValuesMap = new HashMap<>();
937
                    if (availableValues != null) {
938
                        for (LabeledValue availableValue : availableValues) {
939
                            availableValuesMap.put(
940
                                    Objects.toString(availableValue.getValue()),
941
                                    availableValue.getLabel()
942
                            );
943
                        }
944
                    }
945
                    String key;
946
                    if (value instanceof Date) {
947
                        DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
948
                        df.setLenient(false);
949
                        key = df.format(value);
950
                    } else {
951
                        key = Objects.toString(value);
952
                    }
953
                    String label = availableValuesMap.getOrDefault(key, key);
954
                    LabeledValueImpl newItem = new LabeledValueImpl(label, value);
955
                    model.addElement(newItem);
956
                    cboValue.setSelectedItem(newItem);
957
                    valueAssigned = newItem;
958
                }
959
            }
960
        });
961
    }
962

    
963
    private Field getCurrentField() {
964
        final Field field = (Field) this.ddnFields.getSelectedItem();
965
        return field;
966
    }
967

    
968
    public int setAttribute(String name) {
969
        ComboBoxModel<Field> model = this.ddnFields.getModel();
970
        for (int i = 0; i < model.getSize(); i++) {
971
            Field x = model.getElementAt(i);
972
            if (StringUtils.equalsIgnoreCase(name, x.getValue())) {
973
                this.setAttribute(i);
974
                return i;
975
            }
976
        }
977
        this.setAttribute(-1);
978
        return -1;
979
    }
980

    
981
    public void setAttribute(int index) {
982
        try {
983
            this.ddnFields.setSelectedIndex(index);
984
        } catch (Exception ex) {
985
            this.ddnFields.setSelectedIndex(-1);
986
        }
987
        doUpdateValuesList();
988
    }
989

    
990
    public int setAttributePath(String[][] pathNames) {
991
        // [[attributeName, storeName],...]
992
        try {
993
            if (pathNames.length == 1) {
994
                String[] path = pathNames[pathNames.length - 1];
995
                String name = path[0];
996
                int index = this.setAttribute(name);
997
                if (index == -1) {
998
                    try {
999
                        FeatureAttributeDescriptor attrDescriptor = store.getDefaultFeatureType().getAttributeDescriptorFromAll(name);
1000
                        if (attrDescriptor == null) {
1001
                            FeatureQuery query = this.parameters.getQuery();
1002
                            if(query != null){
1003
                                attrDescriptor = query.getExtraColumns().get(name);
1004
                            }
1005
                        }
1006
                        if (attrDescriptor == null) {
1007
                            I18nManager i18n = ToolsLocator.getI18nManager();
1008
                            ThreadSafeDialogsManager dialogManager = ToolsSwingLocator.getThreadSafeDialogsManager();
1009
                            dialogManager.messageDialog(
1010
                                    i18n.getTranslation("_It_is_not_supported_to_search_through_this_field") + ":\n " + name + "\n"
1011
                                    + i18n.getTranslation("_Field_not_found_in_this_table"),
1012
                                    "_Warning",
1013
                                    JOptionPane.WARNING_MESSAGE
1014
                            );
1015
                            this.cboValue.setModel(new DefaultComboBoxModel());
1016
                        } else {
1017
                            FeatureAttributeDescriptor[] attributePath = new FeatureAttributeDescriptor[]{attrDescriptor};
1018
                            doAddAndSelect(store, attrDescriptor, attributePath);
1019
                        }
1020
                    } catch (Exception ex) {
1021
                        LOGGER.warn("Not able to set single path into controller", ex);
1022
                        return -1;
1023
                    }
1024
                }
1025
                return index;
1026
            } else {
1027
                ComboBoxModel<Field> model = this.ddnFields.getModel();
1028
                String[] singleArrayPathNameDescriptors = new String[pathNames.length];
1029
                for (int i = 0; i < pathNames.length; i++) {
1030
                    singleArrayPathNameDescriptors[i] = pathNames[i][0];
1031
                }
1032
                // check the drop
1033
                for (int i = 0; i < model.getSize(); i++) {
1034
                    Field x = model.getElementAt(i);
1035
                    String[] arrayDescriptors = new String[x.getPath().length];
1036
                    FeatureAttributeDescriptor[] path = x.getPath();
1037
                    for (int j = 0; j < path.length; j++) {
1038
                        arrayDescriptors[j] = path[j].getName();
1039
                    }
1040
                    if (Arrays.equals(singleArrayPathNameDescriptors, arrayDescriptors)) {
1041
                        this.setAttribute(i);
1042
                        return i;
1043
                    }
1044
                }
1045
                // if not, addit to the drop
1046
                DataManager dataManager = DALLocator.getDataManager();
1047
                String tableName = pathNames[pathNames.length - 1][1]; // del ultimo path, coger el nombre tabla
1048
                FeatureStore theStore = (FeatureStore) dataManager.getStoresRepository().getStore(tableName);
1049
                String attributeName = pathNames[pathNames.length - 1][0]; // del ultimo path, coger el nombre attribute
1050
                if (theStore != null) {
1051
                    FeatureAttributeDescriptor attr;
1052
                    try {
1053
                        attr = theStore.getDefaultFeatureType().getAttributeDescriptor(attributeName);
1054
                        FeatureAttributeDescriptor[] attributePath = new FeatureAttributeDescriptor[2];
1055
                        String firstAttrName = pathNames[0][0];
1056
                        FeatureAttributeDescriptor firstAttr = store.getDefaultFeatureType().getAttributeDescriptor(firstAttrName);
1057
                        attributePath[0] = firstAttr;
1058

    
1059
                        attributePath[1] = attr;
1060
                        doAddAndSelect(theStore, attr, attributePath);
1061
                        return SIZE_ORDERED_ATTRIBUTES - 1;
1062
                    } catch (Exception ex) {
1063
                        LOGGER.warn("Not able to set foreign path into controller", ex);
1064
                    }
1065

    
1066
                }
1067

    
1068
            }
1069
        } catch (Exception ex) {
1070
            LOGGER.warn("Controller not set.", ex);
1071
        }
1072
        this.setAttribute(-1);
1073
        return -1;
1074
    }
1075

    
1076
    private boolean isTheSameStore(DataStore store1, DataStore store2) {
1077
        String store1FullName = store1.getFullName();
1078
        String store2FullName = store2.getFullName();
1079
        return StringUtils.equalsIgnoreCase(store1FullName, store2FullName);
1080
    }
1081

    
1082
    private String getPrimaryKeyName(FeatureStore store) {
1083
        try {
1084
            FeatureAttributeDescriptor[] pk = store.getDefaultFeatureType().getPrimaryKey();
1085
            if (pk == null || pk.length != 1) {
1086
                return null;
1087
            }
1088
            return pk[0].getName();
1089
        } catch (DataException ex) {
1090
            return null;
1091
        }
1092
    }
1093

    
1094
    private String getForeingKeyName(FeatureStore store, FeatureStore foreingStore) {
1095
        try {
1096
            for (FeatureAttributeDescriptor descriptor : store.getDefaultFeatureType()) {
1097
                if (descriptor.isForeingKey()) {
1098
                    ForeingKey foreingKey = descriptor.getForeingKey();
1099
                    if (isTheSameStore(foreingStore, foreingKey.getFeatureStore(null))) {
1100
                        return descriptor.getName();
1101
                    }
1102
                }
1103
            }
1104
        } catch (DataException ex) {
1105
            return null;
1106
        }
1107
        return null;
1108
    }
1109

    
1110
    public boolean isValid(StringBuilder message) {
1111
        try {
1112
            Object value = this.getValue();
1113
            if (value == null) {
1114
                return true;
1115
            }
1116
            Field field = this.getCurrentField();
1117
            if (field == null) {
1118
                return true;
1119
            }
1120
            if (field.getPath().length > 2) {
1121
                message.append("Invalid field '").append(field.getLabel()).append("'.\n");
1122
                return false;
1123
            }
1124
            FeatureAttributeDescriptor descriptor = field.getDescriptor();
1125
            switch (this.getRelationalOperator()) {
1126
                case ExpressionBuilder.OPERATOR_EQ:
1127
                case ExpressionBuilder.OPERATOR_NE:
1128
                case ExpressionBuilder.OPERATOR_GT:
1129
                case ExpressionBuilder.OPERATOR_GE:
1130
                case ExpressionBuilder.OPERATOR_LT:
1131
                case ExpressionBuilder.OPERATOR_LE:
1132
        try {
1133
                    descriptor.getDataType().coerce(value);
1134
                } catch (CoercionException ex) {
1135
                    message.append("Invalid value '")
1136
                            .append(Objects.toString(value))
1137
                            .append("' for field '")
1138
                            .append(descriptor.getLabel())
1139
                            .append("'.");
1140
                    message.append("\n");
1141
                    message.append(ex.getMessage());
1142
                    message.append("\n");
1143
                    return false;
1144
                }
1145
                break;
1146

    
1147
                default:
1148
                case ExpressionBuilder.OPERATOR_ILIKE:
1149
                case OPERATOR_CONTAINS:
1150
                    break;
1151
            }
1152
            return true;
1153
        } catch (Exception ex) {
1154
            message.append("Invalid values '").append(ex.toString());
1155
            return false;
1156
        }
1157
    }
1158

    
1159
    public ExpressionBuilder.Value getFilter() {
1160
        StringBuilder warns = new StringBuilder();
1161
        return this.getFilter(warns);
1162
    }
1163

    
1164
    public ExpressionBuilder.Value getFilter(StringBuilder warnings) {
1165
        ExpressionBuilder.Value filter = null;
1166

    
1167
        Field field = this.getCurrentField();
1168
        if (field == null) {
1169
            return null;
1170
        }
1171
        if (field.getPath().length > 2) {
1172
            // No soportado
1173
            warnings.append("Lookups are only supported on directly related tables.");
1174
            return null;
1175
        }
1176
        DataManager dataManager = DALLocator.getDataManager();
1177
        DALExpressionBuilder builder = dataManager.createDALExpressionBuilder();
1178
        FeatureAttributeDescriptor parentDescriptor = field.getParentDescriptor();
1179
        FeatureAttributeDescriptor descriptor = field.getDescriptor();
1180
        
1181
        switch(descriptor.getType()) {
1182
            case DataTypes.GEOMETRY:
1183
                filter = this.createGeometryFilter(builder, parentDescriptor, descriptor, field, warnings);
1184
                if( filter == null ) {
1185
                    return null;
1186
                }
1187
                filter = builder.expression().group(filter);
1188
                return filter;
1189
            case DataTypes.DATE:
1190
            default:
1191
        }        
1192
        Object value = null;
1193
        ExpressionBuilder.Constant value_constant = null;
1194

    
1195
        String operator = this.getRelationalOperator();
1196
        switch (operator) {
1197
            case ExpressionBuilder.OPERATOR_IS_NULL:
1198
                value = this.getValue();
1199
                filter = getFilterForOperatorNull(parentDescriptor, descriptor, builder, field);
1200
                return filter;
1201
            case ExpressionBuilder.OPERATOR_IS_NOT_NULL:
1202
                value = this.getValue();
1203
                filter = getFilterForOperatorNotNull(parentDescriptor, descriptor, builder, field);
1204
                return filter;
1205
            case ExpressionBuilder.OPERATOR_EQ:
1206
            case ExpressionBuilder.OPERATOR_NE:
1207
            case ExpressionBuilder.OPERATOR_GT:
1208
            case ExpressionBuilder.OPERATOR_GE:
1209
            case ExpressionBuilder.OPERATOR_LT:
1210
            case ExpressionBuilder.OPERATOR_LE:
1211
                value = this.getValue();
1212
                if (value == null ) {
1213
                    return null;
1214
                }
1215
                try {
1216
                    value_constant = builder.expression().constant(
1217
                            descriptor.getDataType().coerce(value)
1218
                    );
1219
                } catch (CoercionException ex) {
1220
                    return null;
1221
                }
1222
                break;
1223

    
1224
            case ExpressionBuilder.OPERATOR_ILIKE:                
1225
                value = this.getValue(false);
1226
                if (value == null ) {
1227
                    return null;
1228
                }
1229
                value_constant = builder.expression().constant(value);
1230
                break;
1231
            default:
1232
            case OPERATOR_CONTAINS:
1233
                value = this.getValue(false);
1234
                if (value == null ) {
1235
                    return null;
1236
                }
1237
                value_constant = builder.expression().constant("%" + value + "%");
1238
                operator = ExpressionBuilder.OPERATOR_ILIKE;
1239
                break;                
1240
        }
1241

    
1242
        ExpressionBuilder.Value fieldOp = null;
1243
        if (parentDescriptor == null) {
1244
            fieldOp = builder.expression().column(this.store.getName(), descriptor.getName());
1245
            if (StringUtils.equalsIgnoreCase(operator, ExpressionBuilder.OPERATOR_ILIKE) && descriptor.getType() != DataTypes.STRING) {
1246
                fieldOp = builder.expression().cast(fieldOp,DataTypes.STRING);
1247
            }
1248

    
1249

    
1250
            // Se busca en campos de la misma tabla.
1251
            filter = builder.expression().binaryOperator(
1252
                    operator,
1253
                    fieldOp,
1254
                    value_constant
1255
            );
1256

    
1257
            ExpressionBuilder.Value nullValue = builder.expression().column(this.store.getName(), descriptor.getName());
1258
            filter = addNullBehavior(builder, filter, nullValue);
1259

    
1260
        } else {
1261
            // Se busca en campos de una tabla relacionada.
1262
            switch (parentDescriptor.getRelationType()) {
1263
                case DynField.RELATION_TYPE_COLLABORATION:
1264
                case DynField.RELATION_TYPE_IDENTITY:
1265
                    fieldOp = builder.foreing_value(
1266
                            parentDescriptor.getName(),
1267
                            descriptor.getName()
1268
                    );
1269
                    if (StringUtils.equalsIgnoreCase(operator, ExpressionBuilder.OPERATOR_ILIKE) && descriptor.getType() != DataTypes.STRING) {
1270
                        fieldOp = builder.expression().cast(fieldOp,DataTypes.STRING);
1271
                    }
1272

    
1273
                    filter = builder.expression().binaryOperator(
1274
                            operator,
1275
                            fieldOp,
1276
                            value_constant
1277
                    );
1278
                    ExpressionBuilder.Value nullValue = builder.foreing_value(
1279
                            parentDescriptor.getName(),
1280
                            descriptor.getName()
1281
                    );
1282
                    filter = addNullBehavior(builder, filter, nullValue);
1283
                    break;
1284

    
1285
                case DynField.RELATION_TYPE_AGGREGATE:
1286
                case DynField.RELATION_TYPE_COMPOSITION:
1287
                    ExpressionBuilder.Value op_composition = null;
1288
                    fieldOp = builder.expression().column(
1289
                            field.getFeatureStore().getName(),
1290
                            descriptor.getName()
1291
                    );
1292
                    if (StringUtils.equalsIgnoreCase(operator, ExpressionBuilder.OPERATOR_ILIKE) && descriptor.getType() != DataTypes.STRING) {
1293
                        fieldOp = builder.expression().cast(fieldOp,DataTypes.STRING);
1294
                    }
1295
                    op_composition = builder.expression().binaryOperator(
1296
                            operator,
1297
                            fieldOp,
1298
                            value_constant
1299
                    );
1300
                    ExpressionBuilder.Value null_value = builder.expression().column(
1301
                            field.getFeatureStore().getName(),
1302
                            descriptor.getName()
1303
                    );
1304
                    op_composition = addNullBehavior(builder, op_composition, null_value);
1305

    
1306
                    filter = buildExists(builder, field, op_composition);
1307
                    break;
1308
            }
1309
        }
1310

    
1311
        filter = builder.expression().group(filter);
1312
        return filter;
1313
    }
1314

    
1315
    private ExpressionBuilder.Value buildExists(DALExpressionBuilder builder, Field field, ExpressionBuilder.Value op_composition) {
1316
        ExpressionBuilder.Value filter;
1317
        SQLBuilder.SelectBuilder select = builder.select();
1318
        select.from().table().name(field.getFeatureStore().getName());
1319
        //select.column().name(parentDescriptor.getFeatureType().getPrimaryKey()[0].getName());
1320
        select.column().value(builder.expression().constant(1));
1321
        select.limit(1);
1322
        select.where().value(
1323
                builder.expression().and(
1324
                        builder.expression().eq(
1325
                                builder.expression().column(
1326
                                        field.getFeatureStore().getName(),
1327
                                        getForeingKeyName(field.getFeatureStore(), this.store)
1328
                                ),
1329
                                builder.expression().column(
1330
                                        this.store.getName(),
1331
                                        getPrimaryKeyName(this.store)
1332
                                )
1333
                        ),
1334
                        op_composition
1335
                )
1336
        );
1337
        filter = builder.exists(select);
1338
        return filter;
1339
    }
1340

    
1341
    public JsonObject toJson() {
1342
        JsonObjectBuilder fieldBuilder = Json.createObjectBuilder();
1343

    
1344
        JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
1345
        Field currentField = this.getCurrentField();
1346
//        if(currentField == null){
1347
//            return null;
1348
//        }
1349
        FeatureAttributeDescriptor[] path = currentField.getPath();
1350
        for (int i = 0; i < path.length; i++) {
1351
            FeatureAttributeDescriptor featureAttributeDescriptor = path[i];
1352
            JsonArrayBuilder pathArray = Json.createArrayBuilder();
1353

    
1354
            //first value: name field
1355
            String fieldName = featureAttributeDescriptor.getName();
1356
            pathArray.add(fieldName);
1357
            //second value: name store
1358
            if(i==0){
1359
                pathArray.add(this.store.getName());
1360
            } else {
1361
                FeatureType featureType = featureAttributeDescriptor.getFeatureType();
1362
                String storeName = featureType.getStore().getName();
1363
                pathArray.add(storeName);
1364
            }
1365
            arrayBuilder.add(pathArray);
1366
        }
1367
        String relational = this.getRelationalOperator();
1368
        Object value = this.getValue(false);
1369
        String strValue = DataTypeUtils.toString(value);
1370
        String logical = this.getLogicalOperator();
1371

    
1372
        fieldBuilder.add("fieldPath", arrayBuilder);
1373
        fieldBuilder.add("relational", relational);
1374
        if (!StringUtils.isEmpty(strValue)) {
1375
            fieldBuilder.add("strValue", strValue);
1376
        }
1377
        if (!StringUtils.isEmpty(logical)) {
1378
            fieldBuilder.add("logical", logical);
1379
        }
1380
        int nullBehavior = this.getNullBehavior();
1381
        fieldBuilder.add("nullBehavior", nullBehavior);
1382
        
1383
        fieldBuilder.add("geometryOperandMode", this.geometryOperandMode);
1384
        fieldBuilder.add("geometryOperandStoreName", this.geometryOperandStoreName);
1385
        fieldBuilder.add("geometryOperandConstant", this.geometryOperandConstant);
1386
        return fieldBuilder.build();
1387
    }
1388
    
1389
    public void put(SearchParameters params, int index) {
1390
        this.parameters = params;
1391
        Map<String, JsonObject> values = params.getValues();
1392
        if( values == null ) {
1393
            return;
1394
        }
1395
        JsonObject panelState = values.getOrDefault(PANEL_NAME, null);
1396
        if( panelState == null ) {
1397
            return;
1398
        }
1399
        String name = DataTypeUtils.toString(index);
1400
        this.fromJson(panelState.getJsonObject(name));
1401
    }
1402
    
1403
    public void fromJson(JsonObject jsonState) {
1404
        if (jsonState == null) {
1405
            return;
1406
        }
1407

    
1408
        JsonArray fieldPath = jsonState.getJsonArray("fieldPath");
1409

    
1410
        // array of arrays
1411
        String[][] arrayNew = new String[fieldPath.size()][2];
1412
        for (int i = 0; i < fieldPath.size(); i++) {
1413
            String[] arrayField = new String[2];
1414
            arrayField[0] = fieldPath.getJsonArray(i).getString(0);
1415
            arrayField[1] = fieldPath.getJsonArray(i).getString(1);
1416
            arrayNew[i] = arrayField;
1417
        }
1418
        this.setAttributePath(arrayNew);  //usar el doAddAndSelect
1419

    
1420
        String relational = jsonState.getString("relational");
1421
        this.setRelationalOperator(relational);
1422

    
1423
        if (jsonState.containsKey("strValue")) {
1424
            String strValue = jsonState.getString("strValue");
1425
//        SwingUtilities.invokeLater(new Runnable() {
1426
//            @Override
1427
//            public void run() {
1428
            setValue(strValue);
1429
//            }
1430
//        });
1431
        }
1432
        if (jsonState.containsKey("logical")) {
1433
            String logical = jsonState.getString("logical");
1434
            this.setLogicalOperator(logical);
1435
        }
1436
        if (jsonState.containsKey("nullBehavior")) {
1437
            int nullBehavior = jsonState.getInt("nullBehavior");
1438
            this.setNullBehavior(nullBehavior);
1439
        }
1440

    
1441
        this.geometryOperandMode = jsonState.getInt("geometryOperandMode", GEOM_OPERAND_MODE_CLIPBOARD);
1442
        this.geometryOperandStoreName = jsonState.getString("geometryOperandStoreName", null);
1443
        this.geometryOperandConstant = (Geometry) Json.toObject(jsonState,"geometryOperandConstant");
1444
    }
1445

    
1446
    public void setUpdateValuesLimits(int limit, int featuresLimit) {
1447
        this.updateValuesTimeLimit = limit;
1448
        this.updateValuesFeaturesLimit = featuresLimit;
1449
        doUpdateValuesList();
1450
    }
1451

    
1452
    public int getNullBehavior() {
1453
        return (int) ((LabeledValue) this.ddnNullBehavior.getSelectedItem()).getValue();
1454
    }
1455

    
1456
    public int setNullBehavior(int nullBehaviorValue) {
1457
        int n = 0;
1458
        for (LabeledValue nullBehavior : nullBehaviors) {
1459
            int toInt = (int) nullBehavior.getValue();
1460
            if (nullBehaviorValue == toInt) {
1461
                break;
1462
            }
1463
            n++;
1464
        }
1465
        if (this.nullBehaviors.length <= n) {
1466
            return -1;
1467
        }
1468
        this.ddnNullBehavior.setSelectedIndex(n);
1469
        return n;
1470
    }
1471

    
1472
    private ExpressionBuilder.Value addNullBehavior(DALExpressionBuilder builder, ExpressionBuilder.Value filter, ExpressionBuilder.Value nullValue) {
1473
        if (this.getRelationalOperator() != ExpressionBuilder.OPERATOR_IS_NULL && this.getRelationalOperator() != ExpressionBuilder.OPERATOR_IS_NOT_NULL) {
1474
            if (this.getNullBehavior() == NULL_AS_TRUE) {
1475
                ExpressionBuilder.Function null_function = builder.expression().is_null(nullValue);
1476
                filter = builder.expression().or(null_function, filter);
1477
            } else if (this.getNullBehavior() == NULL_AS_FALSE) {
1478
                ExpressionBuilder.Function null_function = builder.expression().not_is_null(nullValue);
1479
                filter = builder.expression().and(null_function, filter);
1480
            }
1481
        }
1482
        return filter;
1483
    }
1484

    
1485
    private ExpressionBuilder.Value getFilterForOperatorNull(
1486
            FeatureAttributeDescriptor parentDescriptor,
1487
            FeatureAttributeDescriptor descriptor,
1488
            DALExpressionBuilder builder,
1489
            Field field) {
1490

    
1491
        ExpressionBuilder.Value filter = null;
1492
        if (parentDescriptor == null) {
1493
            filter = builder.expression().is_null(builder.expression().column(this.store.getName(), descriptor.getName()));
1494
        } else {
1495
            // Se busca en campos de una tabla relacionada.
1496
            switch (parentDescriptor.getRelationType()) {
1497
                case DynField.RELATION_TYPE_COLLABORATION:
1498
                case DynField.RELATION_TYPE_IDENTITY:
1499
                    filter = builder.expression().is_null(builder.foreing_value(
1500
                            parentDescriptor.getName(),
1501
                            descriptor.getName()
1502
                    ));
1503
                    break;
1504
                case DynField.RELATION_TYPE_AGGREGATE:
1505
                case DynField.RELATION_TYPE_COMPOSITION:
1506
                    ExpressionBuilder.Value op_composition = null;
1507
                    op_composition = builder.expression().is_null(builder.expression().column(
1508
                            field.getFeatureStore().getName(),
1509
                            descriptor.getName()
1510
                    ));
1511
                    filter = buildExists(builder, field, op_composition);
1512
            }
1513
        }
1514

    
1515
        filter = builder.expression().group(filter);
1516
        return filter;
1517
    }
1518

    
1519
    private ExpressionBuilder.Value getFilterForOperatorNotNull(
1520
            FeatureAttributeDescriptor parentDescriptor,
1521
            FeatureAttributeDescriptor descriptor,
1522
            DALExpressionBuilder builder,
1523
            Field field) {
1524

    
1525
        ExpressionBuilder.Value filter = null;
1526
        if (parentDescriptor == null) {
1527
            filter = builder.expression().not_is_null(builder.expression().column(this.store.getName(), descriptor.getName()));
1528
        } else {
1529
            // Se busca en campos de una tabla relacionada.
1530
            switch (parentDescriptor.getRelationType()) {
1531
                case DynField.RELATION_TYPE_COLLABORATION:
1532
                case DynField.RELATION_TYPE_IDENTITY:
1533
                    filter = builder.expression().not_is_null(builder.foreing_value(
1534
                            parentDescriptor.getName(),
1535
                            descriptor.getName()
1536
                    ));
1537
                    break;
1538
                case DynField.RELATION_TYPE_AGGREGATE:
1539
                case DynField.RELATION_TYPE_COMPOSITION:
1540
                    ExpressionBuilder.Value op_composition = null;
1541
                    op_composition = builder.expression().not_is_null(builder.expression().column(
1542
                            field.getFeatureStore().getName(),
1543
                            descriptor.getName()
1544
                    ));
1545

    
1546
                    filter = buildExists(builder, field, op_composition);
1547
            }
1548
        }
1549

    
1550
        filter = builder.expression().group(filter);
1551
        return filter;
1552
    }
1553

    
1554
    private ExpressionBuilder.Value createGeometryFilter(
1555
            DALExpressionBuilder builder, 
1556
            FeatureAttributeDescriptor parentDescriptor, 
1557
            FeatureAttributeDescriptor descriptor, 
1558
            Field field,
1559
            StringBuilder warnings
1560
        ) {
1561
        ExpressionBuilder.Value filter = null;
1562

    
1563
        if( parentDescriptor!=null ) {
1564
            return null; //FIXME
1565
        }
1566
        Geometry geometry = this.getGeometryOperand(descriptor.getSRS(), warnings);
1567
        String operator = this.getRelationalOperator();
1568
        switch (operator) {
1569
            case ExpressionBuilder.OPERATOR_IS_NULL:
1570
                filter = getFilterForOperatorNull(parentDescriptor, descriptor, builder, field);
1571
                break;
1572
            case ExpressionBuilder.OPERATOR_IS_NOT_NULL:
1573
                filter = getFilterForOperatorNotNull(parentDescriptor, descriptor, builder, field);
1574
                break;
1575
            case GeometryExpressionBuilder.FUNCTION_ST_CONTAINS:
1576
            case GeometryExpressionBuilder.FUNCTION_ST_COVERS:
1577
            case GeometryExpressionBuilder.FUNCTION_ST_COVEREDBY:
1578
            case GeometryExpressionBuilder.FUNCTION_ST_CROSSES:
1579
            case GeometryExpressionBuilder.FUNCTION_ST_DISJOINT:
1580
            case GeometryExpressionBuilder.FUNCTION_ST_EQUALS:
1581
            case GeometryExpressionBuilder.FUNCTION_ST_INTERSECTS:
1582
            case GeometryExpressionBuilder.FUNCTION_ST_OVERLAPS: 
1583
            case GeometryExpressionBuilder.FUNCTION_ST_WITHIN: 
1584
            case GeometryExpressionBuilder.FUNCTION_ST_TOUCHES:
1585
                if( geometry==null ) {
1586
                    return null; // FIXME
1587
                }
1588
                filter = builder.expression().function(
1589
                        operator,
1590
                        builder.expression().column(descriptor.getName()),
1591
                        builder.expression().geometry(geometry)
1592
                );
1593
                break;
1594
            case GeometryExpressionBuilder.FUNCTION_ST_ISCLOSED:
1595
                filter = builder.expression().function(
1596
                        operator,
1597
                        builder.expression().column(descriptor.getName())
1598
                );
1599
                break;
1600
            default:
1601
                return null;
1602
        }
1603
        if( filter!=null ) {
1604
            String s = filter.toString();
1605
            if( s.length()>10000 ) {
1606
                warnings.append("There are many selected geometries or they are very large.");
1607
                warnings.append("\n");
1608
            }
1609
        }
1610
        return filter;
1611
    }
1612

    
1613
    private Geometry getGeometryOperand(IProjection proj, StringBuilder warnings) {
1614
        List<Geometry> geoms;
1615
        switch(this.geometryOperandMode) {
1616
            case GEOM_OPERAND_MODE_LAYER_SELECTION:
1617
                geoms = this.getGeometryOperandFromLayerSelection(this.geometryOperandStoreName, warnings);
1618
                break;
1619
            case GEOM_OPERAND_MODE_CONSTANT:
1620
                geoms = this.getGeometryOperandConstant(proj, warnings);
1621
                break;
1622
            case GEOM_OPERAND_MODE_CLIPBOARD:
1623
                geoms = this.getGeometryOperandFromClipboard(proj, warnings);
1624
                break;
1625
            case GEOM_OPERAND_MODE_EMPTY:
1626
            default:
1627
                return null;
1628
        }
1629
        if( geoms==null || geoms.isEmpty() ) {
1630
            return null;
1631
        }
1632
        if( geoms.size()==1 ) {
1633
            return geoms.get(0);
1634
        }
1635
        Geometry geom = GeometryUtils.toAggregate(geoms, warnings);
1636
        if( geom!=null && geom.getProjection()==null ) {
1637
            geom.setProjection(proj);
1638
        }
1639
        return geom;
1640
    }
1641
    
1642
    private List<Geometry> getGeometryOperandConstant(IProjection proj, StringBuilder warnings) {
1643
        if( this.geometryOperandConstant==null ) {
1644
            warnings.append("The geometry with which to operate has not been indicated");
1645
            warnings.append("\n");
1646
            return null;
1647
        }
1648
        if( this.geometryOperandConstant.getProjection()==null ) {
1649
            this.geometryOperandConstant.setProjection(proj);
1650
        }
1651
        return Collections.singletonList(this.geometryOperandConstant);
1652
    }
1653
    
1654
    private List<Geometry> getGeometryOperandFromClipboard(IProjection proj, StringBuilder warnings) {
1655
        try {
1656
            ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
1657

    
1658
            String s = toolsSwingManager.getFromClipboard();
1659
            if( StringUtils.isBlank(s) ) {
1660
                warnings.append("The clipboard is empty");
1661
                warnings.append("\n");
1662
                return null;
1663
            }
1664
            List<Geometry> geom = GeometryUtils.extractFrom(s, proj);
1665
            if( geom == null ) {
1666
                warnings.append("Can't locate geometries in clipboard");
1667
                warnings.append("\n");
1668
                return null;
1669
            }
1670
            return geom;
1671
        } catch (Exception ex) {
1672
            LOGGER.warn("Can't get geometry value.", ex);
1673
            warnings.append("Can't extract a geometry from clipboard");
1674
            warnings.append("\n(");
1675
            warnings.append(ex.getLocalizedMessage());
1676
            warnings.append(")\n");
1677
            return null;
1678
        }
1679
    }
1680
    
1681
    private synchronized List<Geometry> getGeometryOperandFromLayerSelection(String storeName, StringBuilder warnings) {
1682
        if( StringUtils.isBlank(storeName) ) {
1683
            return null;
1684
        }        
1685
        StoresRepository repo = null;
1686
        FeatureStore theStore = null;
1687
        try {
1688
            repo = DALLocator.getDataManager().getStoresRepository();
1689
            theStore = (FeatureStore) repo.getStore(storeName);
1690
            if( theStore == null ) {
1691
                warnings.append("Table not found in project.");
1692
                warnings.append("\n");
1693
                return null;
1694
            }
1695
            String geomAttrName = theStore.getDefaultFeatureTypeQuietly().getDefaultGeometryAttributeName();
1696
            if( StringUtils.isEmpty(geomAttrName) ) {
1697
                warnings.append("The selected table can't have geometries");
1698
                warnings.append("\n");
1699
                return null;
1700
            }
1701
            if( theStore.isFeatureSelectionEmpty() ) {
1702
                warnings.append("The selection of the selected table is empty.");
1703
                warnings.append("\n");
1704
                return null;
1705
            }
1706
            Iterator<FeatureReference> it = theStore.getFeatureSelectionQuietly().referenceIterator();
1707
            List<Geometry> geoms = new ArrayList<>();
1708
            for (Feature feature : theStore.getFeaturesIterable(it)) {
1709
                geoms.add(feature.getGeometry(geomAttrName));
1710
            }
1711
            return geoms;
1712
        } finally {
1713
            DisposeUtils.dispose(theStore);
1714
        }
1715
    }
1716
    
1717
    private void doSelectGeometryOperand() {
1718
        I18nManager i18n = ToolsLocator.getI18nManager();
1719
        WindowManager_v2 windowManager = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
1720
        SelectGeometryPanel panel = new SelectGeometryPanel();
1721
        Dialog dialog = windowManager.createDialog(
1722
                panel, 
1723
                i18n.getTranslation("_Indicate_where_to_obtain_the_geometries"), 
1724
                null, 
1725
                WindowManager_v2.BUTTONS_OK_CANCEL
1726
        );
1727
        dialog.addActionListener((ActionEvent e) -> {
1728
            if( dialog.getAction()==WindowManager_v2.BUTTON_OK ) {
1729
                this.geometryOperandMode = panel.getMode();
1730
                this.geometryOperandConstant = panel.getGeometry();
1731
                this.geometryOperandStoreName = panel.getStoreName();
1732
                doUpdateCurrentValue();
1733
            }
1734
        });
1735
        dialog.show(WindowManager.MODE.DIALOG);
1736
    }
1737
    
1738
    public String getWarnings() {
1739
        StringBuilder warns = new StringBuilder();
1740
        ExpressionBuilder.Value filter = this.getFilter(warns);
1741
        String s = warns.toString();
1742
        if( StringUtils.isBlank(s) ) {
1743
            return null;
1744
        }
1745
        return s;
1746
    }
1747
}