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 @ 47564

History | View | Annotate | Download (79.3 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 String FUNCTION_ISNOTVALID = "IsNotValid";
105
    /*friend*/ static final String FUNCTION_INTERSECTSWITHBBOX = "IntersectsWithBBox";
106
    
107
    /*friend*/ static final int GEOM_OPERAND_MODE_EMPTY = 0;
108
    /*friend*/ static final int GEOM_OPERAND_MODE_CLIPBOARD = 1;
109
    /*friend*/ static final int GEOM_OPERAND_MODE_LAYER_SELECTION = 2;
110
    /*friend*/ static final int GEOM_OPERAND_MODE_CONSTANT = 3;
111
    
112
    private static final String OPERATOR_CONTAINS = "CONTAINS";
113

    
114
    private class UpdateValueList implements Runnable, CancellableTask {
115

    
116
        private final Field field;
117
        private boolean cancelled;
118

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

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

    
256
        @Override
257
        public boolean isCancellationRequested() {
258
            return this.cancelled;
259
        }
260

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

    
270
        FeatureAttributeDescriptor attrdesc;
271
        private final FeatureStore store;
272
        private final int presentationMode;
273
        private final boolean showStoreName;
274
        private final FeatureAttributeDescriptor[] path;
275

    
276
        public Field(FeatureAttributeDescriptor[] path, FeatureStore store, FeatureAttributeDescriptor attrdesc, int presentationMode) {
277
            this(path, store, attrdesc, presentationMode, false);
278
        }
279

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

    
298
        public FeatureAttributeDescriptor[] getPath() {
299
            return this.path;
300
        }
301

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

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

    
326
        public FeatureAttributeDescriptor getDescriptor() {
327
            return this.attrdesc;
328
        }
329

    
330
        public FeatureStore getFeatureStore() {
331
            return this.store;
332
        }
333

    
334
    }
335

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

    
348
    private DropDown ddnFields;
349
    private DropDown ddnLogicalOperators;
350
    private DropDown ddnRelationalOperators;
351
    private DropDown ddnNullBehavior;
352

    
353
    private LabeledValue[] relationalOperators;
354
    private LabeledValue[] logicalOperators;
355
    private LabeledValue[] nullBehaviors;
356
    private ArrayList<ImageIcon> nullOperatorsIcons;
357

    
358
    private final int SIZE_ORDERED_ATTRIBUTES = 20;
359
    private DatePickerController dateController = null;
360

    
361
    private int updateValuesTimeLimit;
362
    private int updateValuesFeaturesLimit;
363

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

    
394
    public boolean isAValidRelationOperator(String name) {
395
        for (LabeledValue relationalOperator : relationalOperators) {
396
            if (StringUtils.equalsIgnoreCase(name, (CharSequence) relationalOperator.getValue())) {
397
                return true;
398
            }
399
        }
400
        return false;
401
    }
402

    
403
    @SuppressWarnings("Convert2Lambda")
404
    private void initComponents() {
405
        try {
406
            I18nManager i18n = ToolsLocator.getI18nManager();
407
            ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
408

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

    
422
            this.geometryRelationalOperators = new LabeledValue[]{
423
                new LabeledValueImpl(i18n.getTranslation("_Is_covered_by"), GeometryExpressionBuilder.FUNCTION_ST_COVEREDBY),
424
                new LabeledValueImpl(i18n.getTranslation("_Covers_to"), GeometryExpressionBuilder.FUNCTION_ST_COVERS),
425
                new LabeledValueImpl(i18n.getTranslation("_Contains_to"), GeometryExpressionBuilder.FUNCTION_ST_CONTAINS),
426
                new LabeledValueImpl(i18n.getTranslation("_Crosses_to"), GeometryExpressionBuilder.FUNCTION_ST_CROSSES),
427
                new LabeledValueImpl(i18n.getTranslation("_Is_disjoint_with"), GeometryExpressionBuilder.FUNCTION_ST_DISJOINT),
428
                new LabeledValueImpl(i18n.getTranslation("_Intersects_with"), GeometryExpressionBuilder.FUNCTION_ST_INTERSECTS),
429
                new LabeledValueImpl(i18n.getTranslation("_Intersects_with_boundingbox"), FUNCTION_INTERSECTSWITHBBOX),
430
//                new LabeledValueImpl(i18n.getTranslation("_Is_closed"), GeometryExpressionBuilder.FUNCTION_ST_ISCLOSED),
431
                new LabeledValueImpl(i18n.getTranslation("_Overlaps_with"), GeometryExpressionBuilder.FUNCTION_ST_OVERLAPS),
432
                new LabeledValueImpl(i18n.getTranslation("_Touches_with"), GeometryExpressionBuilder.FUNCTION_ST_TOUCHES),
433
                new LabeledValueImpl(i18n.getTranslation("_Is_within_of"), GeometryExpressionBuilder.FUNCTION_ST_WITHIN),
434
                new LabeledValueImpl(i18n.getTranslation("_Is_equals_to"), GeometryExpressionBuilder.FUNCTION_ST_EQUALS),
435
                new LabeledValueImpl(i18n.getTranslation("_Is_null"), ExpressionBuilder.OPERATOR_IS_NULL),
436
                new LabeledValueImpl(i18n.getTranslation("_Is_not_null"), ExpressionBuilder.OPERATOR_IS_NOT_NULL),
437
                new LabeledValueImpl(i18n.getTranslation("_Is_valid"), GeometryExpressionBuilder.FUNCTION_ST_ISVALID),
438
                new LabeledValueImpl(i18n.getTranslation("_Is_not_valid"), FUNCTION_ISNOTVALID)
439
            };
440

    
441
            logicalOperators = new LabeledValue[]{
442
                new LabeledValueImpl(i18n.getTranslation("_Or"), ExpressionBuilder.OPERATOR_OR),
443
                new LabeledValueImpl(i18n.getTranslation("_And"), ExpressionBuilder.OPERATOR_AND)
444
            };
445

    
446
            nullBehaviors = new LabeledValue[]{
447
                new LabeledValueImpl(i18n.getTranslation("_Not_handle_null_values"), NOT_HANDLE_NULL),
448
                new LabeledValueImpl(i18n.getTranslation("_Null_values_as_true"), NULL_AS_TRUE),
449
                new LabeledValueImpl(i18n.getTranslation("_Null_values_as_false"), NULL_AS_FALSE)
450
            };
451

    
452
            nullOperatorsIcons = new ArrayList<ImageIcon>();
453
            nullOperatorsIcons.add(ToolsSwingLocator.getIconThemeManager().getCurrent().get("search-nullbehavior-null"));
454
            nullOperatorsIcons.add(ToolsSwingLocator.getIconThemeManager().getCurrent().get("search-nullbehavior-true"));
455
            nullOperatorsIcons.add(ToolsSwingLocator.getIconThemeManager().getCurrent().get("search-nullbehavior-false"));
456

    
457
            this.lblExtraFields.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
458

    
459
            this.ddnFields = toolsSwingManager.createDropDown(lblFields);
460
            this.ddnFields.setVisibleDropdownArrow(false);
461
            this.ddnRelationalOperators = toolsSwingManager.createDropDown(lblRelationalOperators);
462
            this.ddnRelationalOperators.setVisibleDropdownArrow(false);
463
            if (lblLogicalOperators != null) {
464
                this.ddnLogicalOperators = toolsSwingManager.createDropDown(lblLogicalOperators);
465
                this.ddnLogicalOperators.setVisibleDropdownArrow(false);
466
            }
467

    
468
            this.modelRelationalOperators = new DefaultComboBoxModel();
469
            for (LabeledValue op : relationalOperators) {
470
                modelRelationalOperators.addElement(op);
471
            }
472
            this.modelGeometryRelationalOperators = new DefaultComboBoxModel();
473
            for (LabeledValue op : geometryRelationalOperators) {
474
                modelGeometryRelationalOperators.addElement(op);
475
            }
476
            this.ddnRelationalOperators.setModel(modelRelationalOperators);
477
            this.ddnRelationalOperators.addItemListener(new ItemListener() {
478
                @Override
479
                public void itemStateChanged(ItemEvent ie) {
480
                    doUpdateControllerByRelationalOperator();
481
                }
482
            });
483

    
484
            if (this.ddnLogicalOperators != null) {
485
                DefaultComboBoxModel modelLogicalOperators = new DefaultComboBoxModel();
486
                for (LabeledValue op : logicalOperators) {
487
                    modelLogicalOperators.addElement(op);
488
                }
489
                this.ddnLogicalOperators.setModel(modelLogicalOperators);
490
                this.ddnLogicalOperators.setSelectedIndex(1);
491
            }
492

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

    
534
            this.ddnFields.setIcons(icons);
535
            this.ddnFields.setModel(model);
536
            this.ddnFields.addItemListener(new ItemListener() {
537
                @Override
538
                public void itemStateChanged(ItemEvent e) {
539
                    if (e.getStateChange() == ItemEvent.SELECTED) {
540
                        doUpdateValuesList();
541
                    }
542

    
543
                }
544
            });
545

    
546
            this.cboValue.addItemListener(new ItemListener() {
547
                @Override
548
                public void itemStateChanged(ItemEvent e) {
549
                    if (e.getStateChange() == ItemEvent.SELECTED) {
550
                        if (cboValue.getSelectedItem() != null && cboValue.getSelectedItem() instanceof LabeledValue) {
551
                            if (Objects.equals(((LabeledValue) cboValue.getSelectedItem()).getValue(), LOAD_MORE_ELEMENTS)) {
552
                                setUpdateValuesLimits(updateValuesTimeLimit + 10, updateValuesFeaturesLimit + 1000);
553
                            }
554
                        }
555
                    }
556
                }
557
            });
558

    
559
            this.lblExtraFields.addMouseListener(new MouseAdapter() {
560
                @Override
561
                public void mouseClicked(MouseEvent e) {
562
                    doSelectMoreFields();
563
                }
564
            });
565
            this.txtValue.setVisible(false);
566
            this.btnValue.setVisible(false);
567
            this.geometryOperandMode = GEOM_OPERAND_MODE_EMPTY;
568
            this.geometryOperandStoreName = null;
569
            this.geometryOperandConstant = null;
570
            this.useBox2dInGeometryOperand = false;
571
            this.btnValue.addActionListener((ActionEvent e) -> {doSelectGeometryOperand(); });
572

    
573
            doUpdateControllerByRelationalOperator();
574
//      clear();
575
        } catch (Exception ex) {
576
            throw new RuntimeException(ex);
577
        }
578
    }
579

    
580
    private void doUpdateControllerByRelationalOperator() {
581
        Object item = ((LabeledValue) ddnRelationalOperators.getSelectedItem()).getValue();
582
        if (ExpressionBuilder.OPERATOR_IS_NULL.equals(item) || ExpressionBuilder.OPERATOR_IS_NOT_NULL.equals(item)) {
583
            lblNull.setEnabled(false);
584
            cboValue.setEnabled(false);
585
            cboValue.setSelectedIndex(-1);
586
        } else {
587
            lblNull.setEnabled(true);
588
            cboValue.setEnabled(true);
589
        }
590
        doUpdateCurrentValue();
591
    }
592

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

    
634
    private FeatureType getFeatureType() {
635
        try {
636
            return this.store.getDefaultFeatureType();
637
        } catch (DataException ex) {
638
            return null;
639
        }
640
    }
641

    
642
    private void doSelectMoreFields() {
643
        DefaultFeatureAttributeSelectionPanel panel = new DefaultFeatureAttributeSelectionPanel(
644
                store, 
645
                parameters.getFeatureType(store),
646
                parameters.getQuery()
647
        );
648
        WindowManager_v2 winManager = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
649
        final Dialog dialog = winManager.createDialog(
650
                panel,
651
                "Select attribute",
652
                null,
653
                WindowManager_v2.BUTTONS_OK_CANCEL
654
        );
655
        dialog.addActionListener((ActionEvent e) -> {
656
            if (dialog.getAction() == WindowManager_v2.BUTTONS_OK) {
657
                doAddAndSelect(
658
                        panel.getSelectedStore(),
659
                        panel.getSelectedAttributeDescriptor(),
660
                        panel.getSelectedPath()
661
                );
662
            }
663
        });
664
        dialog.show(WindowManager.MODE.DIALOG);
665

    
666
    }
667

    
668
    private void doAddAndSelect(FeatureStore theStore, FeatureAttributeDescriptor attrdesc, FeatureAttributeDescriptor[] path) {
669
        ThreadSafeDialogsManager dialogManager = ToolsSwingLocator.getThreadSafeDialogsManager();
670
        I18nManager i18n = ToolsLocator.getI18nManager();
671
        DefaultComboBoxModel<Field> model = (DefaultComboBoxModel) this.ddnFields.getModel();
672
        if (attrdesc == null) {
673
            dialogManager.messageDialog(
674
                    i18n.getTranslation("_It_is_not_supported_to_search_through_this_field") + "\n"
675
                    + i18n.getTranslation("_Field_not_found"),
676
                    "_Warning",
677
                    JOptionPane.WARNING_MESSAGE
678
            );
679
            return;
680
        }
681

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

    
738
    public void clear() {
739
        this.ddnRelationalOperators.setSelectedIndex(0);
740
        if (this.ddnLogicalOperators != null) {
741
            this.ddnLogicalOperators.setSelectedIndex(1);
742
        }
743
        this.cboValue.setSelectedIndex(-1);
744
        this.ddnNullBehavior.setSelectedIndex(0);
745
        this.geometryOperandStoreName = null;
746
        this.geometryOperandMode = GEOM_OPERAND_MODE_EMPTY;
747
        doUpdateControllerByRelationalOperator();
748
    }
749

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

    
820
    public void setEnabled(boolean enabled) {
821
        ddnFields.setEnabled(enabled);
822
        if (ddnLogicalOperators != null) {
823
            ddnLogicalOperators.setEnabled(enabled);
824
        }
825
        ddnRelationalOperators.setEnabled(enabled);
826
        lblExtraFields.setEnabled(enabled);
827
        cboValue.setEnabled(enabled);
828
        doUpdateControllerByRelationalOperator();
829
    }
830

    
831
    public String getRelationalOperator() {
832
        LabeledValue<String> op = (LabeledValue) this.ddnRelationalOperators.getSelectedItem();
833
        if (op == null) {
834
            return null;
835
        }
836
        return op.getValue();
837
    }
838

    
839
    public int setRelationalOperator(String name) {
840
        int n = 0;
841
        for (LabeledValue relationalOperator : relationalOperators) {
842
            if (StringUtils.equalsIgnoreCase(name, (CharSequence) relationalOperator.getValue())) {
843
                break;
844
            }
845
            n++;
846
        }
847
        if (this.relationalOperators.length <= n) {
848
            return -1;
849
        }
850
        this.ddnRelationalOperators.setSelectedIndex(n);
851
        doUpdateControllerByRelationalOperator();
852
        return n;
853
    }
854

    
855
    public String getLogicalOperator() {
856
        if (this.ddnLogicalOperators == null) {
857
            return null;
858
        }
859
        LabeledValue<String> rel = (LabeledValue) this.ddnLogicalOperators.getSelectedItem();
860
        if (rel == null) {
861
            return null;
862
        }
863
        return rel.getValue();
864
    }
865

    
866
    public void setLogicalOperator(String operator) {
867
        if (this.ddnLogicalOperators == null) {
868
            return;
869
        }
870
        ComboBoxModel model = this.ddnLogicalOperators.getModel();
871
        for (int i = 0; i < model.getSize(); i++) {
872
            LabeledValue modelValue = (LabeledValue) model.getElementAt(i);
873
            String value = (String) modelValue.getValue();
874
            if (StringUtils.equals(value, operator)) {
875
                this.ddnLogicalOperators.setSelectedIndex(i);
876
                break;
877
            }
878
        }
879
    }
880
    
881
    public Object getValue() {
882
        return this.getValue(true);
883
    }
884

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

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

    
971
    private Field getCurrentField() {
972
        final Field field = (Field) this.ddnFields.getSelectedItem();
973
        return field;
974
    }
975

    
976
    public int setAttribute(String name) {
977
        ComboBoxModel<Field> model = this.ddnFields.getModel();
978
        for (int i = 0; i < model.getSize(); i++) {
979
            Field x = model.getElementAt(i);
980
            if (StringUtils.equalsIgnoreCase(name, x.getValue())) {
981
                this.setAttribute(i);
982
                return i;
983
            }
984
        }
985
        this.setAttribute(-1);
986
        return -1;
987
    }
988

    
989
    public void setAttribute(int index) {
990
        try {
991
            this.ddnFields.setSelectedIndex(index);
992
        } catch (Exception ex) {
993
            this.ddnFields.setSelectedIndex(-1);
994
        }
995
        doUpdateValuesList();
996
    }
997

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

    
1067
                        attributePath[1] = attr;
1068
                        doAddAndSelect(theStore, attr, attributePath);
1069
                        return SIZE_ORDERED_ATTRIBUTES - 1;
1070
                    } catch (Exception ex) {
1071
                        LOGGER.warn("Not able to set foreign path into controller", ex);
1072
                    }
1073

    
1074
                }
1075

    
1076
            }
1077
        } catch (Exception ex) {
1078
            LOGGER.warn("Controller not set.", ex);
1079
        }
1080
        this.setAttribute(-1);
1081
        return -1;
1082
    }
1083

    
1084
    private boolean isTheSameStore(DataStore store1, DataStore store2) {
1085
        String store1FullName = store1.getFullName();
1086
        String store2FullName = store2.getFullName();
1087
        return StringUtils.equalsIgnoreCase(store1FullName, store2FullName);
1088
    }
1089

    
1090
    private String getPrimaryKeyName(FeatureStore store) {
1091
        try {
1092
            FeatureAttributeDescriptor[] pk = store.getDefaultFeatureType().getPrimaryKey();
1093
            if (pk == null || pk.length != 1) {
1094
                return null;
1095
            }
1096
            return pk[0].getName();
1097
        } catch (DataException ex) {
1098
            return null;
1099
        }
1100
    }
1101

    
1102
    private String getForeingKeyName(FeatureStore store, FeatureStore foreingStore) {
1103
        try {
1104
            for (FeatureAttributeDescriptor descriptor : store.getDefaultFeatureType()) {
1105
                if (descriptor.isForeingKey()) {
1106
                    ForeingKey foreingKey = descriptor.getForeingKey();
1107
                    if (isTheSameStore(foreingStore, foreingKey.getFeatureStore(null))) {
1108
                        return descriptor.getName();
1109
                    }
1110
                }
1111
            }
1112
        } catch (DataException ex) {
1113
            return null;
1114
        }
1115
        return null;
1116
    }
1117

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

    
1155
                default:
1156
                case ExpressionBuilder.OPERATOR_ILIKE:
1157
                case OPERATOR_CONTAINS:
1158
                    break;
1159
            }
1160
            return true;
1161
        } catch (Exception ex) {
1162
            message.append("Invalid values '").append(ex.toString());
1163
            return false;
1164
        }
1165
    }
1166

    
1167
    public ExpressionBuilder.Value getFilter() {
1168
        StringBuilder warns = new StringBuilder();
1169
        return this.getFilter(warns);
1170
    }
1171

    
1172
    public ExpressionBuilder.Value getFilter(StringBuilder warnings) {
1173
        ExpressionBuilder.Value filter = null;
1174

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

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

    
1232
            case ExpressionBuilder.OPERATOR_ILIKE:                
1233
                value = this.getValue(false);
1234
                if (value == null ) {
1235
                    return null;
1236
                }
1237
                value_constant = builder.expression().constant(value);
1238
                break;
1239
            default:
1240
            case OPERATOR_CONTAINS:
1241
                value = this.getValue(false);
1242
                if (value == null ) {
1243
                    return null;
1244
                }
1245
                value_constant = builder.expression().constant("%" + value + "%");
1246
                operator = ExpressionBuilder.OPERATOR_ILIKE;
1247
                break;                
1248
        }
1249

    
1250
        ExpressionBuilder.Value fieldOp = null;
1251
        if (parentDescriptor == null) {
1252
            fieldOp = builder.expression().column(this.store.getName(), descriptor.getName());
1253
            if (StringUtils.equalsIgnoreCase(operator, ExpressionBuilder.OPERATOR_ILIKE) && descriptor.getType() != DataTypes.STRING) {
1254
                fieldOp = builder.expression().cast(fieldOp,DataTypes.STRING);
1255
            }
1256

    
1257

    
1258
            // Se busca en campos de la misma tabla.
1259
            filter = builder.expression().binaryOperator(
1260
                    operator,
1261
                    fieldOp,
1262
                    value_constant
1263
            );
1264

    
1265
            ExpressionBuilder.Value nullValue = builder.expression().column(this.store.getName(), descriptor.getName());
1266
            filter = addNullBehavior(builder, filter, nullValue);
1267

    
1268
        } else {
1269
            // Se busca en campos de una tabla relacionada.
1270
            switch (parentDescriptor.getRelationType()) {
1271
                case DynField.RELATION_TYPE_COLLABORATION:
1272
                case DynField.RELATION_TYPE_IDENTITY:
1273
                    fieldOp = builder.foreing_value(
1274
                            parentDescriptor.getName(),
1275
                            descriptor.getName()
1276
                    );
1277
                    if (StringUtils.equalsIgnoreCase(operator, ExpressionBuilder.OPERATOR_ILIKE) && descriptor.getType() != DataTypes.STRING) {
1278
                        fieldOp = builder.expression().cast(fieldOp,DataTypes.STRING);
1279
                    }
1280

    
1281
                    filter = builder.expression().binaryOperator(
1282
                            operator,
1283
                            fieldOp,
1284
                            value_constant
1285
                    );
1286
                    ExpressionBuilder.Value nullValue = builder.foreing_value(
1287
                            parentDescriptor.getName(),
1288
                            descriptor.getName()
1289
                    );
1290
                    filter = addNullBehavior(builder, filter, nullValue);
1291
                    break;
1292

    
1293
                case DynField.RELATION_TYPE_AGGREGATE:
1294
                case DynField.RELATION_TYPE_COMPOSITION:
1295
                    ExpressionBuilder.Value op_composition = null;
1296
                    fieldOp = builder.expression().column(
1297
                            field.getFeatureStore().getName(),
1298
                            descriptor.getName()
1299
                    );
1300
                    if (StringUtils.equalsIgnoreCase(operator, ExpressionBuilder.OPERATOR_ILIKE) && descriptor.getType() != DataTypes.STRING) {
1301
                        fieldOp = builder.expression().cast(fieldOp,DataTypes.STRING);
1302
                    }
1303
                    op_composition = builder.expression().binaryOperator(
1304
                            operator,
1305
                            fieldOp,
1306
                            value_constant
1307
                    );
1308
                    ExpressionBuilder.Value null_value = builder.expression().column(
1309
                            field.getFeatureStore().getName(),
1310
                            descriptor.getName()
1311
                    );
1312
                    op_composition = addNullBehavior(builder, op_composition, null_value);
1313

    
1314
                    filter = buildExists(builder, field, op_composition);
1315
                    break;
1316
            }
1317
        }
1318

    
1319
        filter = builder.expression().group(filter);
1320
        return filter;
1321
    }
1322

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

    
1349
    public JsonObject toJson() {
1350
        JsonObjectBuilder fieldBuilder = Json.createObjectBuilder();
1351

    
1352
        JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
1353
        Field currentField = this.getCurrentField();
1354
//        if(currentField == null){
1355
//            return null;
1356
//        }
1357
        FeatureAttributeDescriptor[] path = currentField.getPath();
1358
        for (int i = 0; i < path.length; i++) {
1359
            FeatureAttributeDescriptor featureAttributeDescriptor = path[i];
1360
            JsonArrayBuilder pathArray = Json.createArrayBuilder();
1361

    
1362
            //first value: name field
1363
            String fieldName = featureAttributeDescriptor.getName();
1364
            pathArray.add(fieldName);
1365
            //second value: name store
1366
            if(i==0){
1367
                pathArray.add(this.store.getName());
1368
            } else {
1369
                FeatureType featureType = featureAttributeDescriptor.getFeatureType();
1370
                String storeName = featureType.getStore().getName();
1371
                pathArray.add(storeName);
1372
            }
1373
            arrayBuilder.add(pathArray);
1374
        }
1375
        String relational = this.getRelationalOperator();
1376
        Object value = this.getValue(false);
1377
        String strValue = DataTypeUtils.toString(value);
1378
        String logical = this.getLogicalOperator();
1379

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

    
1417
        JsonArray fieldPath = jsonState.getJsonArray("fieldPath");
1418

    
1419
        // array of arrays
1420
        String[][] arrayNew = new String[fieldPath.size()][2];
1421
        for (int i = 0; i < fieldPath.size(); i++) {
1422
            String[] arrayField = new String[2];
1423
            arrayField[0] = fieldPath.getJsonArray(i).getString(0);
1424
            arrayField[1] = fieldPath.getJsonArray(i).getString(1);
1425
            arrayNew[i] = arrayField;
1426
        }
1427
        this.setAttributePath(arrayNew);  //usar el doAddAndSelect
1428

    
1429
        String relational = jsonState.getString("relational");
1430
        this.setRelationalOperator(relational);
1431

    
1432
        if (jsonState.containsKey("strValue")) {
1433
            String strValue = jsonState.getString("strValue");
1434
//        SwingUtilities.invokeLater(new Runnable() {
1435
//            @Override
1436
//            public void run() {
1437
            setValue(strValue);
1438
//            }
1439
//        });
1440
        }
1441
        if (jsonState.containsKey("logical")) {
1442
            String logical = jsonState.getString("logical");
1443
            this.setLogicalOperator(logical);
1444
        }
1445
        if (jsonState.containsKey("nullBehavior")) {
1446
            int nullBehavior = jsonState.getInt("nullBehavior");
1447
            this.setNullBehavior(nullBehavior);
1448
        }
1449

    
1450
        this.geometryOperandMode = jsonState.getInt("geometryOperandMode", GEOM_OPERAND_MODE_CLIPBOARD);
1451
        this.geometryOperandStoreName = jsonState.getString("geometryOperandStoreName", null);
1452
        this.geometryOperandConstant = (Geometry) Json.toObject(jsonState,"geometryOperandConstant");
1453
        this.useBox2dInGeometryOperand = jsonState.getBoolean("geometryOperandStoreName", false);
1454
    }
1455

    
1456
    public void setUpdateValuesLimits(int limit, int featuresLimit) {
1457
        this.updateValuesTimeLimit = limit;
1458
        this.updateValuesFeaturesLimit = featuresLimit;
1459
        doUpdateValuesList();
1460
    }
1461

    
1462
    public int getNullBehavior() {
1463
        return (int) ((LabeledValue) this.ddnNullBehavior.getSelectedItem()).getValue();
1464
    }
1465

    
1466
    public int setNullBehavior(int nullBehaviorValue) {
1467
        int n = 0;
1468
        for (LabeledValue nullBehavior : nullBehaviors) {
1469
            int toInt = (int) nullBehavior.getValue();
1470
            if (nullBehaviorValue == toInt) {
1471
                break;
1472
            }
1473
            n++;
1474
        }
1475
        if (this.nullBehaviors.length <= n) {
1476
            return -1;
1477
        }
1478
        this.ddnNullBehavior.setSelectedIndex(n);
1479
        return n;
1480
    }
1481

    
1482
    private ExpressionBuilder.Value addNullBehavior(DALExpressionBuilder builder, ExpressionBuilder.Value filter, ExpressionBuilder.Value nullValue) {
1483
        if (this.getRelationalOperator() != ExpressionBuilder.OPERATOR_IS_NULL && this.getRelationalOperator() != ExpressionBuilder.OPERATOR_IS_NOT_NULL) {
1484
            if (this.getNullBehavior() == NULL_AS_TRUE) {
1485
                ExpressionBuilder.Function null_function = builder.expression().is_null(nullValue);
1486
                filter = builder.expression().or(null_function, filter);
1487
            } else if (this.getNullBehavior() == NULL_AS_FALSE) {
1488
                ExpressionBuilder.Function null_function = builder.expression().not_is_null(nullValue);
1489
                filter = builder.expression().and(null_function, filter);
1490
            }
1491
        }
1492
        return filter;
1493
    }
1494

    
1495
    private ExpressionBuilder.Value getFilterForOperatorNull(
1496
            FeatureAttributeDescriptor parentDescriptor,
1497
            FeatureAttributeDescriptor descriptor,
1498
            DALExpressionBuilder builder,
1499
            Field field) {
1500

    
1501
        ExpressionBuilder.Value filter = null;
1502
        if (parentDescriptor == null) {
1503
            filter = builder.expression().is_null(builder.expression().column(this.store.getName(), descriptor.getName()));
1504
        } else {
1505
            // Se busca en campos de una tabla relacionada.
1506
            switch (parentDescriptor.getRelationType()) {
1507
                case DynField.RELATION_TYPE_COLLABORATION:
1508
                case DynField.RELATION_TYPE_IDENTITY:
1509
                    filter = builder.expression().is_null(builder.foreing_value(
1510
                            parentDescriptor.getName(),
1511
                            descriptor.getName()
1512
                    ));
1513
                    break;
1514
                case DynField.RELATION_TYPE_AGGREGATE:
1515
                case DynField.RELATION_TYPE_COMPOSITION:
1516
                    ExpressionBuilder.Value op_composition = null;
1517
                    op_composition = builder.expression().is_null(builder.expression().column(
1518
                            field.getFeatureStore().getName(),
1519
                            descriptor.getName()
1520
                    ));
1521
                    filter = buildExists(builder, field, op_composition);
1522
            }
1523
        }
1524

    
1525
        filter = builder.expression().group(filter);
1526
        return filter;
1527
    }
1528

    
1529
    private ExpressionBuilder.Value getFilterForOperatorNotNull(
1530
            FeatureAttributeDescriptor parentDescriptor,
1531
            FeatureAttributeDescriptor descriptor,
1532
            DALExpressionBuilder builder,
1533
            Field field) {
1534

    
1535
        ExpressionBuilder.Value filter = null;
1536
        if (parentDescriptor == null) {
1537
            filter = builder.expression().not_is_null(builder.expression().column(this.store.getName(), descriptor.getName()));
1538
        } else {
1539
            // Se busca en campos de una tabla relacionada.
1540
            switch (parentDescriptor.getRelationType()) {
1541
                case DynField.RELATION_TYPE_COLLABORATION:
1542
                case DynField.RELATION_TYPE_IDENTITY:
1543
                    filter = builder.expression().not_is_null(builder.foreing_value(
1544
                            parentDescriptor.getName(),
1545
                            descriptor.getName()
1546
                    ));
1547
                    break;
1548
                case DynField.RELATION_TYPE_AGGREGATE:
1549
                case DynField.RELATION_TYPE_COMPOSITION:
1550
                    ExpressionBuilder.Value op_composition = null;
1551
                    op_composition = builder.expression().not_is_null(builder.expression().column(
1552
                            field.getFeatureStore().getName(),
1553
                            descriptor.getName()
1554
                    ));
1555

    
1556
                    filter = buildExists(builder, field, op_composition);
1557
            }
1558
        }
1559

    
1560
        filter = builder.expression().group(filter);
1561
        return filter;
1562
    }
1563

    
1564
    private ExpressionBuilder.Value getFilterForOperatorIsNotValid(
1565
            FeatureAttributeDescriptor parentDescriptor,
1566
            FeatureAttributeDescriptor descriptor,
1567
            DALExpressionBuilder builder,
1568
            Field field) {
1569

    
1570
        ExpressionBuilder.Value filter = null;
1571
        if (parentDescriptor == null) {
1572
            filter = builder.expression().not(
1573
                    builder.expression().ST_IsValid(
1574
                            builder.expression().column(this.store.getName(), descriptor.getName())
1575
                    )
1576
            );
1577
        } else {
1578
            // Se busca en campos de una tabla relacionada.
1579
            switch (parentDescriptor.getRelationType()) {
1580
                case DynField.RELATION_TYPE_COLLABORATION:
1581
                case DynField.RELATION_TYPE_IDENTITY:
1582
                    filter = builder.expression().not(
1583
                        builder.expression().ST_IsValid(
1584
                            builder.foreing_value(
1585
                                parentDescriptor.getName(),
1586
                                descriptor.getName()
1587
                            )
1588
                        )
1589
                    );
1590
                    break;
1591
                case DynField.RELATION_TYPE_AGGREGATE:
1592
                case DynField.RELATION_TYPE_COMPOSITION:
1593
                    ExpressionBuilder.Value op_composition = null;
1594
                    op_composition = builder.expression().not(
1595
                        builder.expression().ST_IsValid(
1596
                            builder.expression().column(
1597
                                field.getFeatureStore().getName(),
1598
                                descriptor.getName()
1599
                            )
1600
                        )
1601
                    );
1602

    
1603
                    filter = buildExists(builder, field, op_composition);
1604
            }
1605
        }
1606

    
1607
        filter = builder.expression().group(filter);
1608
        return filter;
1609
    }
1610

    
1611
    private ExpressionBuilder.Value getFilterForOperatorIsValid(
1612
            FeatureAttributeDescriptor parentDescriptor,
1613
            FeatureAttributeDescriptor descriptor,
1614
            DALExpressionBuilder builder,
1615
            Field field) {
1616

    
1617
        ExpressionBuilder.Value filter = null;
1618
        if (parentDescriptor == null) {
1619
            filter =builder.expression().ST_IsValid(
1620
                builder.expression().column(this.store.getName(), descriptor.getName())
1621
            );
1622
        } else {
1623
            // Se busca en campos de una tabla relacionada.
1624
            switch (parentDescriptor.getRelationType()) {
1625
                case DynField.RELATION_TYPE_COLLABORATION:
1626
                case DynField.RELATION_TYPE_IDENTITY:
1627
                    filter = builder.expression().ST_IsValid(
1628
                            builder.foreing_value(
1629
                                parentDescriptor.getName(),
1630
                                descriptor.getName()
1631
                            )
1632
                    );
1633
                    break;
1634
                case DynField.RELATION_TYPE_AGGREGATE:
1635
                case DynField.RELATION_TYPE_COMPOSITION:
1636
                    ExpressionBuilder.Value op_composition = null;
1637
                    op_composition = 
1638
                        builder.expression().ST_IsValid(
1639
                            builder.expression().column(
1640
                                field.getFeatureStore().getName(),
1641
                                descriptor.getName()
1642
                            )
1643
                    );
1644

    
1645
                    filter = buildExists(builder, field, op_composition);
1646
            }
1647
        }
1648

    
1649
        filter = builder.expression().group(filter);
1650
        return filter;
1651
    }
1652

    
1653
    private ExpressionBuilder.Value createGeometryFilter(
1654
            DALExpressionBuilder builder, 
1655
            FeatureAttributeDescriptor parentDescriptor, 
1656
            FeatureAttributeDescriptor descriptor, 
1657
            Field field,
1658
            StringBuilder warnings
1659
        ) {
1660
        ExpressionBuilder.Value filter = null;
1661

    
1662
        if( parentDescriptor!=null ) {
1663
            return null; //FIXME
1664
        }
1665
        Geometry geometry = this.getGeometryOperand(descriptor.getSRS(), warnings);
1666
        String operator = this.getRelationalOperator();
1667
        switch (operator) {
1668
            case ExpressionBuilder.OPERATOR_IS_NULL:
1669
                filter = getFilterForOperatorNull(parentDescriptor, descriptor, builder, field);
1670
                break;
1671
            case ExpressionBuilder.OPERATOR_IS_NOT_NULL:
1672
                filter = getFilterForOperatorNotNull(parentDescriptor, descriptor, builder, field);
1673
                break;
1674
            case GeometryExpressionBuilder.FUNCTION_ST_ISVALID:
1675
                filter = getFilterForOperatorIsValid(parentDescriptor, descriptor, builder, field);
1676
                break;
1677
            case FUNCTION_ISNOTVALID:
1678
                filter = getFilterForOperatorIsNotValid(parentDescriptor, descriptor, builder, field);
1679
                break;
1680
                
1681
                
1682
            case FUNCTION_INTERSECTSWITHBBOX:
1683
                if( geometry==null ) {
1684
                    return null; // FIXME
1685
                }
1686
                filter = builder.expression().ST_Intersects(
1687
                        builder.expression().ST_Envelope(
1688
                            builder.expression().column(descriptor.getName())
1689
                        ),
1690
                        builder.expression().geometry(geometry)
1691
                );
1692
                break;
1693
            case GeometryExpressionBuilder.FUNCTION_ST_CONTAINS:
1694
            case GeometryExpressionBuilder.FUNCTION_ST_COVERS:
1695
            case GeometryExpressionBuilder.FUNCTION_ST_COVEREDBY:
1696
            case GeometryExpressionBuilder.FUNCTION_ST_CROSSES:
1697
            case GeometryExpressionBuilder.FUNCTION_ST_DISJOINT:
1698
            case GeometryExpressionBuilder.FUNCTION_ST_EQUALS:
1699
            case GeometryExpressionBuilder.FUNCTION_ST_INTERSECTS:
1700
            case GeometryExpressionBuilder.FUNCTION_ST_OVERLAPS: 
1701
            case GeometryExpressionBuilder.FUNCTION_ST_WITHIN: 
1702
            case GeometryExpressionBuilder.FUNCTION_ST_TOUCHES:
1703
                if( geometry==null ) {
1704
                    return null; // FIXME
1705
                }
1706
                filter = builder.expression().function(
1707
                        operator,
1708
                        builder.expression().column(descriptor.getName()),
1709
                        builder.expression().geometry(geometry)
1710
                );
1711
                break;
1712
            case GeometryExpressionBuilder.FUNCTION_ST_ISCLOSED:
1713
                filter = builder.expression().function(
1714
                        operator,
1715
                        builder.expression().column(descriptor.getName())
1716
                );
1717
                break;
1718
            default:
1719
                return null;
1720
        }
1721
        if( filter!=null ) {
1722
            String s = filter.toString();
1723
            if( s.length()>10000 ) {
1724
                warnings.append("There are many selected geometries or they are very large.");
1725
                warnings.append("\n");
1726
            }
1727
        }
1728
        return filter;
1729
    }
1730

    
1731
    private Geometry getGeometryOperand(IProjection proj, StringBuilder warnings) {
1732
        List<Geometry> geoms;
1733
        switch(this.geometryOperandMode) {
1734
            case GEOM_OPERAND_MODE_LAYER_SELECTION:
1735
                geoms = this.getGeometryOperandFromLayerSelection(this.geometryOperandStoreName, warnings);
1736
                break;
1737
            case GEOM_OPERAND_MODE_CONSTANT:
1738
                geoms = this.getGeometryOperandConstant(proj, warnings);
1739
                break;
1740
            case GEOM_OPERAND_MODE_CLIPBOARD:
1741
                geoms = this.getGeometryOperandFromClipboard(proj, warnings);
1742
                break;
1743
            case GEOM_OPERAND_MODE_EMPTY:
1744
            default:
1745
                return null;
1746
        }
1747
        if( geoms==null || geoms.isEmpty() ) {
1748
            return null;
1749
        }
1750
        if( geoms.size()==1 ) {
1751
            return geoms.get(0);
1752
        }
1753
        Geometry geom = GeometryUtils.toAggregate(geoms, warnings);
1754
        if( geom!=null && geom.getProjection()==null ) {
1755
            geom.setProjection(proj);
1756
        }
1757
        return geom;
1758
    }
1759
    
1760
    private List<Geometry> getGeometryOperandConstant(IProjection proj, StringBuilder warnings) {
1761
        if( this.geometryOperandConstant==null ) {
1762
            warnings.append("The geometry with which to operate has not been indicated");
1763
            warnings.append("\n");
1764
            return null;
1765
        }
1766
        if( this.geometryOperandConstant.getProjection()==null ) {
1767
            this.geometryOperandConstant.setProjection(proj);
1768
        }
1769
        return Collections.singletonList(this.geometryOperandConstant);
1770
    }
1771
    
1772
    private List<Geometry> getGeometryOperandFromClipboard(IProjection proj, StringBuilder warnings) {
1773
        try {
1774
            ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
1775

    
1776
            String s = toolsSwingManager.getFromClipboard();
1777
            if( StringUtils.isBlank(s) ) {
1778
                warnings.append("The clipboard is empty");
1779
                warnings.append("\n");
1780
                return null;
1781
            }
1782
            List<Geometry> geom = GeometryUtils.extractFrom(s, proj);
1783
            if( geom == null ) {
1784
                warnings.append("Can't locate geometries in clipboard");
1785
                warnings.append("\n");
1786
                return null;
1787
            }
1788
            return geom;
1789
        } catch (Exception ex) {
1790
            LOGGER.warn("Can't get geometry value.", ex);
1791
            warnings.append("Can't extract a geometry from clipboard");
1792
            warnings.append("\n(");
1793
            warnings.append(ex.getLocalizedMessage());
1794
            warnings.append(")\n");
1795
            return null;
1796
        }
1797
    }
1798
    
1799
    private synchronized List<Geometry> getGeometryOperandFromLayerSelection(String storeName, StringBuilder warnings) {
1800
        if( StringUtils.isBlank(storeName) ) {
1801
            return null;
1802
        }        
1803
        StoresRepository repo = null;
1804
        FeatureStore theStore = null;
1805
        try {
1806
            repo = DALLocator.getDataManager().getStoresRepository();
1807
            theStore = (FeatureStore) repo.getStore(storeName);
1808
            if( theStore == null ) {
1809
                warnings.append("Table not found in project.");
1810
                warnings.append("\n");
1811
                return null;
1812
            }
1813
            String geomAttrName = theStore.getDefaultFeatureTypeQuietly().getDefaultGeometryAttributeName();
1814
            if( StringUtils.isEmpty(geomAttrName) ) {
1815
                warnings.append("The selected table can't have geometries");
1816
                warnings.append("\n");
1817
                return null;
1818
            }
1819
            if( theStore.isFeatureSelectionEmpty() ) {
1820
                warnings.append("The selection of the selected table is empty.");
1821
                warnings.append("\n");
1822
                return null;
1823
            }
1824
            Iterator<FeatureReference> it = theStore.getFeatureSelectionQuietly().referenceIterator();
1825
            List<Geometry> geoms = new ArrayList<>();
1826
            for (Feature feature : theStore.getFeaturesIterable(it)) {
1827
                if(  this.useBox2dInGeometryOperand ) {
1828
                    geoms.add(feature.getGeometry(geomAttrName).getEnvelope().getBox2D());
1829
                } else {
1830
                    geoms.add(feature.getGeometry(geomAttrName));
1831
                }
1832
            }
1833
            return geoms;
1834
        } finally {
1835
            DisposeUtils.dispose(theStore);
1836
        }
1837
    }
1838
    
1839
    private void doSelectGeometryOperand() {
1840
        I18nManager i18n = ToolsLocator.getI18nManager();
1841
        WindowManager_v2 windowManager = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
1842
        SelectGeometryPanel panel = new SelectGeometryPanel();
1843
        Dialog dialog = windowManager.createDialog(
1844
                panel, 
1845
                i18n.getTranslation("_Indicate_where_to_obtain_the_geometries"), 
1846
                null, 
1847
                WindowManager_v2.BUTTONS_OK_CANCEL
1848
        );
1849
        dialog.addActionListener((ActionEvent e) -> {
1850
            if( dialog.getAction()==WindowManager_v2.BUTTON_OK ) {
1851
                this.geometryOperandMode = panel.getMode();
1852
                this.geometryOperandConstant = panel.getGeometry();
1853
                this.geometryOperandStoreName = panel.getStoreName();
1854
                this.useBox2dInGeometryOperand = panel.useBox2dInGeometryOperand();
1855
                doUpdateCurrentValue();
1856
            }
1857
        });
1858
        panel.setMode(this.geometryOperandMode);
1859
        panel.setGeometry(this.geometryOperandConstant);
1860
        panel.setStoreName(this.geometryOperandStoreName);
1861
        panel.setUseBox2dInGeometryOperand(this.useBox2dInGeometryOperand);
1862
        
1863
        dialog.show(WindowManager.MODE.DIALOG);
1864
    }
1865
    
1866
    public String getWarnings() {
1867
        StringBuilder warns = new StringBuilder();
1868
        ExpressionBuilder.Value filter = this.getFilter(warns);
1869
        String s = warns.toString();
1870
        if( StringUtils.isBlank(s) ) {
1871
            return null;
1872
        }
1873
        return s;
1874
    }
1875
}