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

History | View | Annotate | Download (82.2 KB)

1 44259 jjdelcerro
package org.gvsig.fmap.dal.swing.impl.searchpanel;
2
3
import java.awt.Cursor;
4 47264 jjdelcerro
import java.awt.Dimension;
5 44262 jjdelcerro
import java.awt.event.ActionEvent;
6 44259 jjdelcerro
import java.awt.event.ItemEvent;
7
import java.awt.event.ItemListener;
8
import java.awt.event.MouseAdapter;
9
import java.awt.event.MouseEvent;
10 45203 omartinez
import java.text.DateFormat;
11 44259 jjdelcerro
import java.util.ArrayList;
12 44842 omartinez
import java.util.Arrays;
13 47264 jjdelcerro
import java.util.Collections;
14 46941 fdiaz
import java.util.Comparator;
15 45203 omartinez
import java.util.Date;
16 44259 jjdelcerro
import java.util.HashMap;
17 47264 jjdelcerro
import java.util.Iterator;
18 44259 jjdelcerro
import java.util.List;
19 45203 omartinez
import java.util.Locale;
20 44259 jjdelcerro
import java.util.Map;
21
import java.util.Objects;
22 47618 jjdelcerro
import java.util.function.Supplier;
23 44829 omartinez
import javax.json.JsonArray;
24
import javax.json.JsonObject;
25 44259 jjdelcerro
import javax.swing.ComboBoxModel;
26
import javax.swing.DefaultComboBoxModel;
27 44263 jjdelcerro
import javax.swing.ImageIcon;
28 47264 jjdelcerro
import javax.swing.JButton;
29 44259 jjdelcerro
import javax.swing.JComboBox;
30
import javax.swing.JLabel;
31 44748 jjdelcerro
import javax.swing.JOptionPane;
32 47264 jjdelcerro
import javax.swing.JTextField;
33 44262 jjdelcerro
import javax.swing.SwingUtilities;
34 45185 jjdelcerro
import javax.swing.text.JTextComponent;
35 44259 jjdelcerro
import org.apache.commons.lang3.StringUtils;
36 46955 fdiaz
import org.apache.commons.lang3.mutable.MutableBoolean;
37 47264 jjdelcerro
import org.cresques.cts.IProjection;
38 44259 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionBuilder;
39 47264 jjdelcerro
import org.gvsig.expressionevaluator.GeometryExpressionBuilder;
40 44750 jjdelcerro
import org.gvsig.fmap.dal.DALLocator;
41 44262 jjdelcerro
import org.gvsig.fmap.dal.DataManager;
42 44748 jjdelcerro
import org.gvsig.fmap.dal.DataStore;
43 47264 jjdelcerro
import org.gvsig.fmap.dal.DataTypes;
44 46517 fdiaz
import org.gvsig.fmap.dal.SQLBuilder;
45 47264 jjdelcerro
import org.gvsig.fmap.dal.StoresRepository;
46 44262 jjdelcerro
import org.gvsig.fmap.dal.complements.Search;
47
import org.gvsig.fmap.dal.exception.DataException;
48 44750 jjdelcerro
import org.gvsig.fmap.dal.expressionevaluator.DALExpressionBuilder;
49 44259 jjdelcerro
import org.gvsig.fmap.dal.feature.Feature;
50
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
51 44374 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureQuery;
52 47264 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureReference;
53 44259 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureSet;
54
import org.gvsig.fmap.dal.feature.FeatureStore;
55
import org.gvsig.fmap.dal.feature.FeatureType;
56 44748 jjdelcerro
import org.gvsig.fmap.dal.feature.ForeingKey;
57 46485 fdiaz
import org.gvsig.fmap.dal.swing.DALSwingLocator;
58 47618 jjdelcerro
import org.gvsig.fmap.dal.swing.DataSwingManager;
59 44713 jjdelcerro
import org.gvsig.fmap.dal.swing.impl.featuretype.DefaultFeatureAttributeSelectionPanel;
60 46501 jjdelcerro
import static org.gvsig.fmap.dal.swing.impl.searchpanel.SearchConditionPanelSimplified.PANEL_NAME;
61 45326 omartinez
import static org.gvsig.fmap.dal.swing.searchpanel.FeatureStoreSearchPanel.NOT_HANDLE_NULL;
62
import static org.gvsig.fmap.dal.swing.searchpanel.FeatureStoreSearchPanel.NULL_AS_FALSE;
63
import static org.gvsig.fmap.dal.swing.searchpanel.FeatureStoreSearchPanel.NULL_AS_TRUE;
64 45222 omartinez
import org.gvsig.fmap.dal.swing.searchpanel.SearchParameters;
65 47264 jjdelcerro
import org.gvsig.fmap.geom.Geometry;
66
import org.gvsig.fmap.geom.GeometryUtils;
67 47618 jjdelcerro
import org.gvsig.fmap.geom.primitive.Envelope;
68 47264 jjdelcerro
import org.gvsig.json.Json;
69
import org.gvsig.json.JsonArrayBuilder;
70
import org.gvsig.json.JsonObjectBuilder;
71 44262 jjdelcerro
import org.gvsig.tools.ToolsLocator;
72 44669 jjdelcerro
import org.gvsig.tools.dataTypes.Coercion;
73 44259 jjdelcerro
import org.gvsig.tools.dataTypes.CoercionException;
74 44829 omartinez
import org.gvsig.tools.dataTypes.DataTypeUtils;
75 45100 jjdelcerro
import org.gvsig.tools.dispose.DisposeUtils;
76 44748 jjdelcerro
import org.gvsig.tools.dynobject.DynField;
77 44688 jjdelcerro
import org.gvsig.tools.i18n.I18nManager;
78 44259 jjdelcerro
import org.gvsig.tools.swing.api.DropDown;
79
import org.gvsig.tools.swing.api.ToolsSwingLocator;
80
import org.gvsig.tools.swing.api.ToolsSwingManager;
81 45185 jjdelcerro
import org.gvsig.tools.swing.api.pickercontroller.DatePickerController;
82 44748 jjdelcerro
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
83 44262 jjdelcerro
import org.gvsig.tools.swing.api.windowmanager.Dialog;
84
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
85
import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2;
86 44263 jjdelcerro
import org.gvsig.tools.swing.icontheme.IconTheme;
87 46955 fdiaz
import org.gvsig.tools.task.CancellableTask;
88 46941 fdiaz
import org.gvsig.tools.util.CompareUtils;
89 44259 jjdelcerro
import org.gvsig.tools.util.LabeledValue;
90
import org.gvsig.tools.util.LabeledValueImpl;
91
import org.gvsig.tools.visitor.VisitCanceledException;
92 44262 jjdelcerro
import org.slf4j.Logger;
93
import org.slf4j.LoggerFactory;
94 44259 jjdelcerro
95
/**
96
 *
97
 * @author jjdelcerro
98
 */
99
@SuppressWarnings("UseSpecificCatch")
100 44713 jjdelcerro
public class SearchConditionFieldController {
101 44259 jjdelcerro
102 45326 omartinez
    private static final Logger LOGGER = LoggerFactory.getLogger(SearchConditionFieldController.class);
103
    private static final Class LOAD_MORE_ELEMENTS = SearchConditionFieldController.class;
104 45331 omartinez
105 45386 jjdelcerro
    private static final int MAXLEN_IN_COMBOS = 70;
106 47564 jjdelcerro
107
    /*friend*/ static final String FUNCTION_ISNOTVALID = "IsNotValid";
108
    /*friend*/ static final String FUNCTION_INTERSECTSWITHBBOX = "IntersectsWithBBox";
109 45386 jjdelcerro
110 47275 jjdelcerro
    /*friend*/ static final int GEOM_OPERAND_MODE_EMPTY = 0;
111
    /*friend*/ static final int GEOM_OPERAND_MODE_CLIPBOARD = 1;
112
    /*friend*/ static final int GEOM_OPERAND_MODE_LAYER_SELECTION = 2;
113
    /*friend*/ static final int GEOM_OPERAND_MODE_CONSTANT = 3;
114 47618 jjdelcerro
    /*friend*/ static final int GEOM_OPERAND_MODE_CURRENT_BOUNDINGBOX = 4;
115 47264 jjdelcerro
116 46846 jjdelcerro
    private static final String OPERATOR_CONTAINS = "CONTAINS";
117 47264 jjdelcerro
118 46955 fdiaz
    private class UpdateValueList implements Runnable, CancellableTask {
119
120
        private final Field field;
121
        private boolean cancelled;
122
123
        public UpdateValueList(Field field) {
124
            this.field = field;
125
        }
126
127
        @Override
128
        public void run() {
129
            if (isCancellationRequested()) {
130
                return;
131
            }
132
            final FeatureStore theStore = field.getFeatureStore();
133
            final FeatureQuery query;
134
            query = theStore.createFeatureQuery();
135
            query.addAttributeName(field.getDescriptor().getName());
136
            query.setFilter("");
137
    //        query.getExtraColumns().copyFrom(this.parameters.getQuery().getExtraColumns());
138
            query.setLimit(updateValuesFeaturesLimit);
139
            query.getGroupByColumns().clear();
140
            query.getAggregateFunctions().clear();
141
142
            FeatureSet set = null;
143
            final List<Object> values = new ArrayList<>();
144
            final DefaultComboBoxModel model = new DefaultComboBoxModel();
145
            MutableBoolean canHasMoreElements = new MutableBoolean();
146
147
            try {
148
                canHasMoreElements.setFalse();
149
                if (isCancellationRequested()) {
150
                    return;
151
                }
152
                set = theStore.getFeatureSet(query);
153
                if (set.size() >= updateValuesFeaturesLimit) {
154
                    canHasMoreElements.setTrue();
155
                }
156
                final long timeLimit = System.currentTimeMillis() + updateValuesTimeLimit * 1000;
157
                set.accept((Object o) -> {
158
                    if (isCancellationRequested()) {
159
                        throw new VisitCanceledException();
160
                    }
161
                    Object value = ((Feature) o).get(field.getDescriptor().getName());
162
                    if (value != null && !values.contains(value)) {
163
                        values.add(value);
164
                    }
165
                    if (System.currentTimeMillis() > timeLimit) {
166
                        canHasMoreElements.setTrue();
167
                        throw new VisitCanceledException();
168
                    }
169
                    if (values.size() > updateValuesFeaturesLimit) {
170
                        canHasMoreElements.setTrue();
171
                        throw new VisitCanceledException();
172
                    }
173
                });
174
            } catch (VisitCanceledException ex) {
175
                canHasMoreElements.setTrue();
176
            } catch (Exception ex) {
177
                canHasMoreElements.setFalse();
178
                LOGGER.warn("Can't update list of values of '" + field.getLabel() + "'.", ex);
179
            } finally {
180
                DisposeUtils.disposeQuietly(set);
181
            }
182
            if (isCancellationRequested()) {
183
                return;
184
            }
185
            List<LabeledValue> elements = new ArrayList<>();
186
            if (!values.isEmpty()) {
187
                LabeledValue[] availableValues = field.getDescriptor().getAvailableValues();
188
                Map<String, String> availableValuesMap = new HashMap<>();
189
                if (availableValues != null) {
190
                    for (LabeledValue availableValue : availableValues) {
191
                        availableValuesMap.put(
192
                                Objects.toString(availableValue.getValue()),
193
                                availableValue.getLabel()
194
                        );
195
                    }
196
                }
197
                elements.add(new LabeledValueImpl("", null, MAXLEN_IN_COMBOS));
198
                for (Object value : values) {
199
                    String key;
200
                    key = DataTypeUtils.toString(value);
201
                    String label = availableValuesMap.getOrDefault(key, key);
202
                    elements.add(new LabeledValueImpl(label, value, MAXLEN_IN_COMBOS));
203
                }
204
                Comparator comparator = null;
205
                if (availableValues == null) {
206
                    switch (field.getDescriptor().getType()) {
207
                        case DataTypes.DATE:
208
                        case DataTypes.TIME:
209
                        case DataTypes.TIMESTAMP:
210
                            comparator = new CompareUtils.NullSafeComparator() {
211
                                @Override
212
                                public int safeCompare(Object o1, Object o2) {
213
                                    Comparable v1 = (Comparable) ((LabeledValue) o1).getValue();
214
                                    Comparable v2 = (Comparable) ((LabeledValue) o2).getValue();
215
                                    if (v1 == v2) {
216
                                        return 0;
217
                                    }
218
                                    if (v1 == null) {
219
                                        return -1;
220
                                    }
221
                                    if (v2 == null) {
222
                                        return 1;
223
                                    }
224
                                    return v1.compareTo(v2);
225
                                }
226
                            };
227
                    }
228
                }
229
                elements.sort(comparator);
230
231
            }
232
            for (LabeledValue element : elements) {
233
                model.addElement(element);
234
            }
235
            if (canHasMoreElements.isTrue()) {
236
                model.addElement(new LabeledValueImpl("...", LOAD_MORE_ELEMENTS));
237
            }
238
            if (isCancellationRequested()) {
239
                return;
240
            }
241
            SwingUtilities.invokeLater(new Runnable() {
242
                @Override
243
                public void run() {
244
                    if (isCancellationRequested()) {
245
                        return;
246
                    }
247
                    setEnabled(false);
248 47264 jjdelcerro
                    Dimension sz = cboValue.getPreferredSize();
249 46955 fdiaz
                    cboValue.setModel(model);
250 47264 jjdelcerro
                    cboValue.setPreferredSize(sz);
251 46955 fdiaz
                    if (valueAssigned != null) {
252
                        cboValue.setSelectedItem(valueAssigned);
253
                        valueAssigned = null;
254
                    }
255
                    setEnabled(true);
256
                }
257
            });
258
        }
259
260
        @Override
261
        public boolean isCancellationRequested() {
262
            return this.cancelled;
263
        }
264
265
        @Override
266
        public void cancelRequest() {
267
            this.cancelled = true;
268
        }
269
270
    }
271
272 45326 omartinez
    private static class Field extends LabeledValueImpl<String> {
273 44259 jjdelcerro
274 45326 omartinez
        FeatureAttributeDescriptor attrdesc;
275
        private final FeatureStore store;
276
        private final int presentationMode;
277
        private final boolean showStoreName;
278
        private final FeatureAttributeDescriptor[] path;
279 44262 jjdelcerro
280 45326 omartinez
        public Field(FeatureAttributeDescriptor[] path, FeatureStore store, FeatureAttributeDescriptor attrdesc, int presentationMode) {
281
            this(path, store, attrdesc, presentationMode, false);
282
        }
283 44262 jjdelcerro
284 45326 omartinez
        public Field(
285
                FeatureAttributeDescriptor[] path,
286
                FeatureStore store,
287
                FeatureAttributeDescriptor attrdesc,
288
                int presentationMode,
289
                boolean showStoreName
290
        ) {
291
            super(
292 46485 fdiaz
                    DALSwingLocator.getDataSwingManager().getAttributeDescriptorLabel(attrdesc, store.getName()),
293 45326 omartinez
                    attrdesc.getName()
294
            );
295
            this.path = path;
296
            this.store = store;
297
            this.attrdesc = attrdesc;
298
            this.presentationMode = presentationMode;
299
            this.showStoreName = showStoreName;
300
        }
301 44750 jjdelcerro
302 45326 omartinez
        public FeatureAttributeDescriptor[] getPath() {
303
            return this.path;
304
        }
305 44262 jjdelcerro
306 45326 omartinez
        @Override
307
        public String getLabel() {
308 47784 jjdelcerro
            DataSwingManager dataSwingManager = DALSwingLocator.getDataSwingManager();
309
            String theLabel;
310
            FeatureAttributeDescriptor parentDescriptor = this.getParentDescriptor();
311
            if( parentDescriptor==null ) {
312
                theLabel = dataSwingManager.getAttributeDescriptorLabel(attrdesc, showStoreName ? store.getName() : null);
313
            } else {
314
                switch (parentDescriptor.getRelationType()) {
315
                    case DynField.RELATION_TYPE_COLLABORATION:
316
                    case DynField.RELATION_TYPE_IDENTITY:
317
                        theLabel = dataSwingManager.getAttributeDescriptorLabel(attrdesc)+" de "+store.getName();
318
                        break; // "_XFieldNameX_of_XTableNameX"
319
320
                    case DynField.RELATION_TYPE_AGGREGATE:
321
                    case DynField.RELATION_TYPE_COMPOSITION:
322
                        theLabel = "\u2203 "+store.getName()+" que "+dataSwingManager.getAttributeDescriptorLabel(attrdesc);
323
                        break; // "_With_some_XTableNameX_that_XFieldNameX". U+2203 -> Exsite alguno
324
                    default:
325
                        theLabel = dataSwingManager.getAttributeDescriptorLabel(attrdesc, showStoreName ? store.getName() : null);
326
                }
327
            }
328 45326 omartinez
            switch (this.presentationMode) {
329
                case Search.OrderedAttribute.TYPE_REGURAL:
330
                    break;
331
                case Search.OrderedAttribute.TYPE_FAVORITE:
332
                    theLabel = "<html><b>" + theLabel + "</b></html>";
333
                    break;
334
                case Search.OrderedAttribute.TYPE_RECENT:
335
                    theLabel = "<html><i><b>" + theLabel + "</b></i></html>";
336
                    break;
337
            }
338
            return theLabel;
339
        }
340 44259 jjdelcerro
341 45326 omartinez
        public FeatureAttributeDescriptor getParentDescriptor() {
342
            int l = this.path.length;
343
            if (l < 2) {
344
                return null;
345
            }
346
            return this.path[l - 2];
347
        }
348 44829 omartinez
349 45326 omartinez
        public FeatureAttributeDescriptor getDescriptor() {
350
            return this.attrdesc;
351
        }
352 44829 omartinez
353 45326 omartinez
        public FeatureStore getFeatureStore() {
354
            return this.store;
355
        }
356
357 44259 jjdelcerro
    }
358 44750 jjdelcerro
359 45326 omartinez
    private FeatureStore store;
360
    private SearchParameters parameters;
361
    private final JLabel lblFields;
362
    private final JLabel lblExtraFields;
363
    private final JLabel lblLogicalOperators;
364
    private final JLabel lblRelationalOperators;
365
    private final JComboBox cboValue;
366 47264 jjdelcerro
    private final JTextField txtValue;
367
    private final JButton btnValue;
368 45326 omartinez
    private final JLabel lblNull;
369
    private Object valueAssigned = null;
370 44829 omartinez
371 45326 omartinez
    private DropDown ddnFields;
372
    private DropDown ddnLogicalOperators;
373
    private DropDown ddnRelationalOperators;
374
    private DropDown ddnNullBehavior;
375 45331 omartinez
376 45326 omartinez
    private LabeledValue[] relationalOperators;
377
    private LabeledValue[] logicalOperators;
378
    private LabeledValue[] nullBehaviors;
379
    private ArrayList<ImageIcon> nullOperatorsIcons;
380 44829 omartinez
381 45326 omartinez
    private final int SIZE_ORDERED_ATTRIBUTES = 20;
382
    private DatePickerController dateController = null;
383 44829 omartinez
384 45326 omartinez
    private int updateValuesTimeLimit;
385
    private int updateValuesFeaturesLimit;
386 44259 jjdelcerro
387 47264 jjdelcerro
    private UpdateValueList updateValueListTask;
388
    private LabeledValue[] geometryRelationalOperators;
389
    private DefaultComboBoxModel modelRelationalOperators;
390
    private DefaultComboBoxModel modelGeometryRelationalOperators;
391
392
    private int geometryOperandMode;
393 47564 jjdelcerro
    private boolean useBox2dInGeometryOperand = false;
394 47672 jjdelcerro
    private String geometryOperandStoreId;
395 47264 jjdelcerro
    private Geometry geometryOperandConstant;
396
397 45326 omartinez
    public SearchConditionFieldController(
398
            SearchParameters parameters,
399
            FeatureStore store,
400 47264 jjdelcerro
            SearchConditionFieldView view
401 45326 omartinez
    ) {
402
        this.parameters = parameters;
403
        this.store = store;
404 47264 jjdelcerro
        this.lblFields = view.lblFields;
405
        this.lblExtraFields = view.lblExtraFields;
406
        this.lblRelationalOperators = view.lblRelationalOperators;
407
        this.cboValue = view.cboValue;
408
        this.txtValue = view.txtValue;
409
        this.btnValue = view.btnValue;
410
        this.lblNull = view.lblNull;
411
        this.lblLogicalOperators = view.lblLogicalOperators;
412 45326 omartinez
        this.updateValuesTimeLimit = 60;
413
        this.updateValuesFeaturesLimit = 1000;
414
        this.initComponents();
415
    }
416 45222 omartinez
417 45326 omartinez
    public boolean isAValidRelationOperator(String name) {
418
        for (LabeledValue relationalOperator : relationalOperators) {
419
            if (StringUtils.equalsIgnoreCase(name, (CharSequence) relationalOperator.getValue())) {
420
                return true;
421
            }
422
        }
423
        return false;
424 44748 jjdelcerro
    }
425 44259 jjdelcerro
426 47264 jjdelcerro
    @SuppressWarnings("Convert2Lambda")
427 45326 omartinez
    private void initComponents() {
428
        try {
429
            I18nManager i18n = ToolsLocator.getI18nManager();
430
            ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
431 44259 jjdelcerro
432 45326 omartinez
            relationalOperators = new LabeledValue[]{
433 46846 jjdelcerro
                new LabeledValueImpl(i18n.getTranslation("_Contains"), OPERATOR_CONTAINS),
434 45326 omartinez
                new LabeledValueImpl(i18n.getTranslation("_Equals_to"), ExpressionBuilder.OPERATOR_EQ),
435
                new LabeledValueImpl(i18n.getTranslation("_Like_to"), ExpressionBuilder.OPERATOR_ILIKE),
436
                new LabeledValueImpl(i18n.getTranslation("_Not_equals_to"), ExpressionBuilder.OPERATOR_NE),
437
                new LabeledValueImpl(i18n.getTranslation("_Greater_than"), ExpressionBuilder.OPERATOR_GT),
438
                new LabeledValueImpl(i18n.getTranslation("_Greater_or_equal_to"), ExpressionBuilder.OPERATOR_GE),
439
                new LabeledValueImpl(i18n.getTranslation("_Less_than"), ExpressionBuilder.OPERATOR_LT),
440
                new LabeledValueImpl(i18n.getTranslation("_Less_or_equal_to"), ExpressionBuilder.OPERATOR_LE),
441
                new LabeledValueImpl(i18n.getTranslation("_Is_null"), ExpressionBuilder.OPERATOR_IS_NULL),
442
                new LabeledValueImpl(i18n.getTranslation("_Is_not_null"), ExpressionBuilder.OPERATOR_IS_NOT_NULL)
443
            };
444 44259 jjdelcerro
445 47264 jjdelcerro
            this.geometryRelationalOperators = new LabeledValue[]{
446
                new LabeledValueImpl(i18n.getTranslation("_Is_covered_by"), GeometryExpressionBuilder.FUNCTION_ST_COVEREDBY),
447
                new LabeledValueImpl(i18n.getTranslation("_Covers_to"), GeometryExpressionBuilder.FUNCTION_ST_COVERS),
448
                new LabeledValueImpl(i18n.getTranslation("_Contains_to"), GeometryExpressionBuilder.FUNCTION_ST_CONTAINS),
449
                new LabeledValueImpl(i18n.getTranslation("_Crosses_to"), GeometryExpressionBuilder.FUNCTION_ST_CROSSES),
450
                new LabeledValueImpl(i18n.getTranslation("_Is_disjoint_with"), GeometryExpressionBuilder.FUNCTION_ST_DISJOINT),
451
                new LabeledValueImpl(i18n.getTranslation("_Intersects_with"), GeometryExpressionBuilder.FUNCTION_ST_INTERSECTS),
452 47564 jjdelcerro
                new LabeledValueImpl(i18n.getTranslation("_Intersects_with_boundingbox"), FUNCTION_INTERSECTSWITHBBOX),
453 47274 jjdelcerro
//                new LabeledValueImpl(i18n.getTranslation("_Is_closed"), GeometryExpressionBuilder.FUNCTION_ST_ISCLOSED),
454 47264 jjdelcerro
                new LabeledValueImpl(i18n.getTranslation("_Overlaps_with"), GeometryExpressionBuilder.FUNCTION_ST_OVERLAPS),
455
                new LabeledValueImpl(i18n.getTranslation("_Touches_with"), GeometryExpressionBuilder.FUNCTION_ST_TOUCHES),
456
                new LabeledValueImpl(i18n.getTranslation("_Is_within_of"), GeometryExpressionBuilder.FUNCTION_ST_WITHIN),
457
                new LabeledValueImpl(i18n.getTranslation("_Is_equals_to"), GeometryExpressionBuilder.FUNCTION_ST_EQUALS),
458
                new LabeledValueImpl(i18n.getTranslation("_Is_null"), ExpressionBuilder.OPERATOR_IS_NULL),
459 47564 jjdelcerro
                new LabeledValueImpl(i18n.getTranslation("_Is_not_null"), ExpressionBuilder.OPERATOR_IS_NOT_NULL),
460
                new LabeledValueImpl(i18n.getTranslation("_Is_valid"), GeometryExpressionBuilder.FUNCTION_ST_ISVALID),
461
                new LabeledValueImpl(i18n.getTranslation("_Is_not_valid"), FUNCTION_ISNOTVALID)
462 47264 jjdelcerro
            };
463
464 45326 omartinez
            logicalOperators = new LabeledValue[]{
465
                new LabeledValueImpl(i18n.getTranslation("_Or"), ExpressionBuilder.OPERATOR_OR),
466
                new LabeledValueImpl(i18n.getTranslation("_And"), ExpressionBuilder.OPERATOR_AND)
467
            };
468 44259 jjdelcerro
469 45326 omartinez
            nullBehaviors = new LabeledValue[]{
470
                new LabeledValueImpl(i18n.getTranslation("_Not_handle_null_values"), NOT_HANDLE_NULL),
471
                new LabeledValueImpl(i18n.getTranslation("_Null_values_as_true"), NULL_AS_TRUE),
472
                new LabeledValueImpl(i18n.getTranslation("_Null_values_as_false"), NULL_AS_FALSE)
473
            };
474 44748 jjdelcerro
475 45326 omartinez
            nullOperatorsIcons = new ArrayList<ImageIcon>();
476
            nullOperatorsIcons.add(ToolsSwingLocator.getIconThemeManager().getCurrent().get("search-nullbehavior-null"));
477
            nullOperatorsIcons.add(ToolsSwingLocator.getIconThemeManager().getCurrent().get("search-nullbehavior-true"));
478 46863 jjdelcerro
            nullOperatorsIcons.add(ToolsSwingLocator.getIconThemeManager().getCurrent().get("search-nullbehavior-false"));
479 44748 jjdelcerro
480 45326 omartinez
            this.lblExtraFields.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
481 44688 jjdelcerro
482 45326 omartinez
            this.ddnFields = toolsSwingManager.createDropDown(lblFields);
483
            this.ddnFields.setVisibleDropdownArrow(false);
484
            this.ddnRelationalOperators = toolsSwingManager.createDropDown(lblRelationalOperators);
485
            this.ddnRelationalOperators.setVisibleDropdownArrow(false);
486
            if (lblLogicalOperators != null) {
487
                this.ddnLogicalOperators = toolsSwingManager.createDropDown(lblLogicalOperators);
488
                this.ddnLogicalOperators.setVisibleDropdownArrow(false);
489
            }
490 45331 omartinez
491 47264 jjdelcerro
            this.modelRelationalOperators = new DefaultComboBoxModel();
492 45326 omartinez
            for (LabeledValue op : relationalOperators) {
493
                modelRelationalOperators.addElement(op);
494
            }
495 47264 jjdelcerro
            this.modelGeometryRelationalOperators = new DefaultComboBoxModel();
496
            for (LabeledValue op : geometryRelationalOperators) {
497
                modelGeometryRelationalOperators.addElement(op);
498
            }
499 45326 omartinez
            this.ddnRelationalOperators.setModel(modelRelationalOperators);
500
            this.ddnRelationalOperators.addItemListener(new ItemListener() {
501
                @Override
502
                public void itemStateChanged(ItemEvent ie) {
503 45331 omartinez
                    doUpdateControllerByRelationalOperator();
504 45326 omartinez
                }
505
            });
506 45331 omartinez
507 45326 omartinez
            if (this.ddnLogicalOperators != null) {
508
                DefaultComboBoxModel modelLogicalOperators = new DefaultComboBoxModel();
509
                for (LabeledValue op : logicalOperators) {
510
                    modelLogicalOperators.addElement(op);
511
                }
512
                this.ddnLogicalOperators.setModel(modelLogicalOperators);
513
                this.ddnLogicalOperators.setSelectedIndex(1);
514
            }
515 45331 omartinez
516 45326 omartinez
            this.ddnNullBehavior = toolsSwingManager.createDropDownIcon(lblNull);
517
            this.ddnNullBehavior.setVisibleDropdownArrow(false);
518
            DefaultComboBoxModel modelNullOperators = new DefaultComboBoxModel();
519
            for (LabeledValue op : nullBehaviors) {
520
                modelNullOperators.addElement(op);
521
            }
522
            this.ddnNullBehavior.setModel(modelNullOperators);
523
            this.ddnNullBehavior.setIcons(nullOperatorsIcons);
524
            this.ddnNullBehavior.setSelectedIndex(0);
525
            FeatureType featureType = parameters.getFeatureType(store);
526
            Search search = (Search) ToolsLocator.getComplementsManager().get(
527
                    Search.COMPLEMENT_MANE, featureType
528
            );
529
            List<Search.OrderedAttribute> orderedAttributes = search.getOrderedAttributes(
530 47292 jjdelcerro
//                    Search.BASIC_TYPES_FILTER,
531
                    Search.BASIC_TYPES_FILTER
532
                        .or((FeatureAttributeDescriptor t) -> t.getType()==DataTypes.GEOMETRY),
533 45326 omartinez
                    Search.STR_INT_LONG_LABEL_ORDER,
534
                    SIZE_ORDERED_ATTRIBUTES
535
            );
536
            List<ImageIcon> icons = new ArrayList<>();
537 44829 omartinez
//            DataTypesManager dataTypeManager = ToolsLocator.getDataTypesManager();
538 45326 omartinez
            IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getCurrent();
539
            DefaultComboBoxModel model = new DefaultComboBoxModel();
540
            for (Search.OrderedAttribute attr : orderedAttributes) {
541
                FeatureAttributeDescriptor attrdesc = attr.getDescriptor();
542
                Field field = new Field(
543
                        new FeatureAttributeDescriptor[]{attrdesc},
544
                        this.store,
545
                        attrdesc,
546
                        attr.getType()
547
                );
548
                model.addElement(field);
549
                String iconName = attrdesc.getDataType().getIconName();
550
                if (iconTheme.exists(iconName)) {
551
                    icons.add(iconTheme.get(iconName));
552
                } else {
553
                    icons.add(null);
554
                }
555
            }
556 44259 jjdelcerro
557 45326 omartinez
            this.ddnFields.setIcons(icons);
558
            this.ddnFields.setModel(model);
559
            this.ddnFields.addItemListener(new ItemListener() {
560
                @Override
561
                public void itemStateChanged(ItemEvent e) {
562
                    if (e.getStateChange() == ItemEvent.SELECTED) {
563
                        doUpdateValuesList();
564
                    }
565
566 45222 omartinez
                }
567 45326 omartinez
            });
568
569
            this.cboValue.addItemListener(new ItemListener() {
570
                @Override
571
                public void itemStateChanged(ItemEvent e) {
572
                    if (e.getStateChange() == ItemEvent.SELECTED) {
573
                        if (cboValue.getSelectedItem() != null && cboValue.getSelectedItem() instanceof LabeledValue) {
574
                            if (Objects.equals(((LabeledValue) cboValue.getSelectedItem()).getValue(), LOAD_MORE_ELEMENTS)) {
575 46941 fdiaz
                                setUpdateValuesLimits(updateValuesTimeLimit + 10, updateValuesFeaturesLimit + 1000);
576 45326 omartinez
                            }
577
                        }
578
                    }
579
                }
580
            });
581
582
            this.lblExtraFields.addMouseListener(new MouseAdapter() {
583
                @Override
584
                public void mouseClicked(MouseEvent e) {
585
                    doSelectMoreFields();
586
                }
587
            });
588 47264 jjdelcerro
            this.txtValue.setVisible(false);
589
            this.btnValue.setVisible(false);
590 47275 jjdelcerro
            this.geometryOperandMode = GEOM_OPERAND_MODE_EMPTY;
591 47672 jjdelcerro
            this.geometryOperandStoreId = null;
592 47264 jjdelcerro
            this.geometryOperandConstant = null;
593 47564 jjdelcerro
            this.useBox2dInGeometryOperand = false;
594 47264 jjdelcerro
            this.btnValue.addActionListener((ActionEvent e) -> {doSelectGeometryOperand(); });
595
596 45331 omartinez
            doUpdateControllerByRelationalOperator();
597 45326 omartinez
//      clear();
598
        } catch (Exception ex) {
599
            throw new RuntimeException(ex);
600 45222 omartinez
        }
601 44829 omartinez
    }
602 44259 jjdelcerro
603 45331 omartinez
    private void doUpdateControllerByRelationalOperator() {
604
        Object item = ((LabeledValue) ddnRelationalOperators.getSelectedItem()).getValue();
605
        if (ExpressionBuilder.OPERATOR_IS_NULL.equals(item) || ExpressionBuilder.OPERATOR_IS_NOT_NULL.equals(item)) {
606
            lblNull.setEnabled(false);
607
            cboValue.setEnabled(false);
608
            cboValue.setSelectedIndex(-1);
609
        } else {
610
            lblNull.setEnabled(true);
611
            cboValue.setEnabled(true);
612
        }
613 47264 jjdelcerro
        doUpdateCurrentValue();
614
    }
615 45331 omartinez
616 47264 jjdelcerro
    private void doUpdateCurrentValue() {
617
        Field field = this.getCurrentField();
618
        if( field!=null ) {
619
            FeatureAttributeDescriptor desc = field.getDescriptor();
620
            int type = desc==null? DataTypes.INT:desc.getType();
621
            switch(type) {
622
                case DataTypes.GEOMETRY:
623
                    this.cboValue.setVisible(false);
624
                    this.txtValue.setVisible(true);
625
                    this.btnValue.setVisible(true);
626
                    switch(this.geometryOperandMode) {
627
                        case GEOM_OPERAND_MODE_CONSTANT:
628
                            if( this.geometryOperandConstant == null ) {
629
                                this.txtValue.setText("");
630
                            } else {
631
                                this.txtValue.setText(Objects.toString(GeometryUtils.toWKT(this.geometryOperandConstant), ""));
632
                            }
633
                            break;
634
                        case GEOM_OPERAND_MODE_LAYER_SELECTION:
635 47672 jjdelcerro
                            if( this.geometryOperandStoreId!=null ) {
636 47264 jjdelcerro
                                StoresRepository repo = DALLocator.getDataManager().getStoresRepository();
637 47672 jjdelcerro
                                this.txtValue.setText(repo.getLabelOrName(this.geometryOperandStoreId));
638 47264 jjdelcerro
                                break;
639
                            }
640
                            this.geometryOperandMode = GEOM_OPERAND_MODE_CLIPBOARD;
641
                        case GEOM_OPERAND_MODE_CLIPBOARD:
642
                            this.txtValue.setText("Contenido del portapapeles"); // i18n.getTranslation("_Clipboard_content"));
643
                            break;
644 47618 jjdelcerro
                        case GEOM_OPERAND_MODE_CURRENT_BOUNDINGBOX:
645
                            DataSwingManager dataSwingManager = DALSwingLocator.getDataSwingManager();
646
                            Supplier<Envelope> bbox = dataSwingManager.getCurrentBoundingBox();
647
                            if( bbox!=null ) {
648
                                Envelope env = bbox.get();
649
                                if( env != null && !env.isEmpty() && !env.isCollapsed() ) {
650
                                    this.txtValue.setText(Objects.toString(GeometryUtils.toWKT(env.getGeometry()), ""));
651
                                } else {
652
                                    this.txtValue.setText("");
653
                                }
654
                            } else {
655
                                this.txtValue.setText("");
656
                            }
657
                            break;
658 47264 jjdelcerro
                    }
659
                    break;
660
                default:
661
                    if( this.txtValue.isVisible() ) {
662
                        this.ddnRelationalOperators.setSelectedIndex(1);
663
                    }
664
                    this.cboValue.setVisible(true);
665
                    this.txtValue.setVisible(false);
666
                    this.btnValue.setVisible(false);
667
            }
668
        }
669 45331 omartinez
    }
670
671 45326 omartinez
    private FeatureType getFeatureType() {
672
        try {
673
            return this.store.getDefaultFeatureType();
674
        } catch (DataException ex) {
675
            return null;
676
        }
677 44829 omartinez
    }
678 44748 jjdelcerro
679 45326 omartinez
    private void doSelectMoreFields() {
680 46501 jjdelcerro
        DefaultFeatureAttributeSelectionPanel panel = new DefaultFeatureAttributeSelectionPanel(
681
                store,
682
                parameters.getFeatureType(store),
683
                parameters.getQuery()
684
        );
685 45326 omartinez
        WindowManager_v2 winManager = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
686
        final Dialog dialog = winManager.createDialog(
687
                panel,
688
                "Select attribute",
689
                null,
690
                WindowManager_v2.BUTTONS_OK_CANCEL
691 44829 omartinez
        );
692 45326 omartinez
        dialog.addActionListener((ActionEvent e) -> {
693
            if (dialog.getAction() == WindowManager_v2.BUTTONS_OK) {
694
                doAddAndSelect(
695
                        panel.getSelectedStore(),
696
                        panel.getSelectedAttributeDescriptor(),
697
                        panel.getSelectedPath()
698
                );
699
            }
700
        });
701
        dialog.show(WindowManager.MODE.DIALOG);
702 44748 jjdelcerro
703 45222 omartinez
    }
704
705 45326 omartinez
    private void doAddAndSelect(FeatureStore theStore, FeatureAttributeDescriptor attrdesc, FeatureAttributeDescriptor[] path) {
706
        ThreadSafeDialogsManager dialogManager = ToolsSwingLocator.getThreadSafeDialogsManager();
707
        I18nManager i18n = ToolsLocator.getI18nManager();
708
        DefaultComboBoxModel<Field> model = (DefaultComboBoxModel) this.ddnFields.getModel();
709
        if (attrdesc == null) {
710
            dialogManager.messageDialog(
711
                    i18n.getTranslation("_It_is_not_supported_to_search_through_this_field") + "\n"
712
                    + i18n.getTranslation("_Field_not_found"),
713
                    "_Warning",
714
                    JOptionPane.WARNING_MESSAGE
715
            );
716
            return;
717
        }
718
719
        for (int i = 0; i < model.getSize(); i++) {
720
            Field field = model.getElementAt(i);
721
            FeatureAttributeDescriptor attrdescN = field.getDescriptor();
722 46171 omartinez
            if (theStore!=null && attrdescN.getStore()!=null && isTheSameStore(theStore, attrdescN.getStore())
723 45326 omartinez
                    && StringUtils.equalsIgnoreCase(attrdesc.getName(), attrdescN.getName())) {
724
                this.setAttribute(i);
725
                return;
726 45084 jjdelcerro
            }
727 45326 omartinez
        }
728
        Field field = new Field(
729
                path,
730
                theStore,
731
                attrdesc,
732
                Search.OrderedAttribute.TYPE_REGURAL,
733
                !isTheSameStore(store, theStore)
734
        );
735
        if (field.getPath().length > 2) {
736
            dialogManager.messageDialog(
737
                    i18n.getTranslation("_It_is_not_supported_to_search_through_this_field") + "\n"
738
                    + i18n.getTranslation("_To_many_links"),
739
                    "_Warning",
740
                    JOptionPane.WARNING_MESSAGE
741
            );
742
            return;
743
        }
744
        FeatureAttributeDescriptor parentDescriptor = field.getParentDescriptor();
745
        if (parentDescriptor != null) {
746
            switch (parentDescriptor.getRelationType()) {
747
                case DynField.RELATION_TYPE_AGGREGATE:
748
                case DynField.RELATION_TYPE_COMPOSITION:
749
                    if (getForeingKeyName(field.getFeatureStore(), this.store) == null) {
750
                        dialogManager.messageDialog(
751
                                "It not supported to search through this field." + "\n"
752
                                + "The link field was not found.",
753
                                "_Warning",
754
                                JOptionPane.WARNING_MESSAGE
755
                        );
756
                        return;
757
                    }
758
                    if (getPrimaryKeyName(this.store) == null) {
759
                        dialogManager.messageDialog(
760
                                "It not supported to search through this field." + "\n"
761
                                + "A simple primary key was not found.",
762
                                "_Warning",
763
                                JOptionPane.WARNING_MESSAGE
764
                        );
765
                        return;
766
                    }
767 45084 jjdelcerro
            }
768 44748 jjdelcerro
        }
769 45326 omartinez
        model.addElement(field);
770
        IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getCurrent();
771
        this.ddnFields.getIcons().add(iconTheme.get(attrdesc.getDataType().getIconName()));
772
        this.setAttribute(model.getSize() - 1);
773 44829 omartinez
    }
774 44262 jjdelcerro
775 45326 omartinez
    public void clear() {
776
        this.ddnRelationalOperators.setSelectedIndex(0);
777
        if (this.ddnLogicalOperators != null) {
778
            this.ddnLogicalOperators.setSelectedIndex(1);
779 45185 jjdelcerro
        }
780 45326 omartinez
        this.cboValue.setSelectedIndex(-1);
781
        this.ddnNullBehavior.setSelectedIndex(0);
782 47672 jjdelcerro
        this.geometryOperandStoreId = null;
783 47275 jjdelcerro
        this.geometryOperandMode = GEOM_OPERAND_MODE_EMPTY;
784 45331 omartinez
        doUpdateControllerByRelationalOperator();
785 45185 jjdelcerro
    }
786 44262 jjdelcerro
787 46505 fdiaz
    private String lastNameInUpdateValuesList = null;
788
    private int lastUpdateValuesFeaturesLimit = -1;
789
    private int lastUpdateValuesTimeLimit = -1;
790
791 45326 omartinez
    private void doUpdateValuesList() {
792
        final Field field = (Field) this.ddnFields.getSelectedItem();
793
        if (field == null) {
794
            return;
795 44855 jjdelcerro
        }
796 45326 omartinez
        FeatureAttributeDescriptor descriptor = field.getDescriptor();
797 46505 fdiaz
        if(StringUtils.equalsIgnoreCase(lastNameInUpdateValuesList, descriptor.getName()) &&
798
                updateValuesFeaturesLimit == lastUpdateValuesFeaturesLimit &&
799
                updateValuesTimeLimit == lastUpdateValuesTimeLimit
800
                ){
801
            return;
802
        }
803
        lastNameInUpdateValuesList = descriptor.getName();
804
        lastUpdateValuesFeaturesLimit = updateValuesFeaturesLimit;
805
        lastUpdateValuesTimeLimit = updateValuesTimeLimit;
806
807 46955 fdiaz
        if(this.updateValueListTask != null){
808
            this.updateValueListTask.cancelRequest();
809
        }
810 47264 jjdelcerro
        Thread updateTask;
811
        switch(descriptor.getType()) {
812
            case DataTypes.GEOMETRY:
813
                this.ddnRelationalOperators.setModel(modelGeometryRelationalOperators);
814
                if( !this.txtValue.isVisible() ) {
815
                    this.ddnRelationalOperators.setSelectedIndex(0);
816
                }
817
                this.cboValue.setVisible(false);
818
                this.txtValue.setVisible(true);
819
                this.btnValue.setVisible(true);
820
                break;
821
            case DataTypes.DATE:
822
                if (this.dateController == null) {
823
                    this.dateController = ToolsSwingLocator.getToolsSwingManager().createDatePickerController(
824
                            (JTextComponent) this.cboValue.getEditor().getEditorComponent(),
825
                            null
826
                    );
827
                }
828
                this.ddnRelationalOperators.setModel(modelRelationalOperators);
829
                if( this.txtValue.isVisible() ) {
830
                    this.ddnRelationalOperators.setSelectedIndex(0);
831
                }
832
                this.cboValue.setVisible(true);
833
                this.txtValue.setVisible(false);
834
                this.btnValue.setVisible(false);
835
                this.updateValueListTask = new UpdateValueList(field);
836
                updateTask = new Thread(updateValueListTask);
837
                updateTask.start();
838
                break;
839
            default:
840
                this.ddnRelationalOperators.setModel(modelRelationalOperators);
841
                if( this.txtValue.isVisible() ) {
842
                    this.ddnRelationalOperators.setSelectedIndex(0);
843
                }
844
                this.cboValue.setVisible(true);
845
                this.txtValue.setVisible(false);
846
                this.btnValue.setVisible(false);
847
                if (this.dateController != null) {
848
                    this.dateController.uninstall();
849
                    this.dateController = null;
850
                }
851
                this.updateValueListTask = new UpdateValueList(field);
852
                updateTask = new Thread(updateValueListTask);
853
                updateTask.start();
854
        }
855 45326 omartinez
    }
856 44829 omartinez
857 45326 omartinez
    public void setEnabled(boolean enabled) {
858
        ddnFields.setEnabled(enabled);
859
        if (ddnLogicalOperators != null) {
860
            ddnLogicalOperators.setEnabled(enabled);
861
        }
862
        ddnRelationalOperators.setEnabled(enabled);
863
        lblExtraFields.setEnabled(enabled);
864
        cboValue.setEnabled(enabled);
865 45331 omartinez
        doUpdateControllerByRelationalOperator();
866 45326 omartinez
    }
867 44829 omartinez
868 45326 omartinez
    public String getRelationalOperator() {
869
        LabeledValue<String> op = (LabeledValue) this.ddnRelationalOperators.getSelectedItem();
870
        if (op == null) {
871
            return null;
872
        }
873
        return op.getValue();
874 44262 jjdelcerro
    }
875
876 45326 omartinez
    public int setRelationalOperator(String name) {
877
        int n = 0;
878
        for (LabeledValue relationalOperator : relationalOperators) {
879
            if (StringUtils.equalsIgnoreCase(name, (CharSequence) relationalOperator.getValue())) {
880
                break;
881
            }
882
            n++;
883
        }
884
        if (this.relationalOperators.length <= n) {
885
            return -1;
886
        }
887
        this.ddnRelationalOperators.setSelectedIndex(n);
888 45331 omartinez
        doUpdateControllerByRelationalOperator();
889 45326 omartinez
        return n;
890 44259 jjdelcerro
    }
891 44262 jjdelcerro
892 45326 omartinez
    public String getLogicalOperator() {
893
        if (this.ddnLogicalOperators == null) {
894
            return null;
895
        }
896
        LabeledValue<String> rel = (LabeledValue) this.ddnLogicalOperators.getSelectedItem();
897
        if (rel == null) {
898
            return null;
899
        }
900
        return rel.getValue();
901 44748 jjdelcerro
    }
902 44262 jjdelcerro
903 45326 omartinez
    public void setLogicalOperator(String operator) {
904
        if (this.ddnLogicalOperators == null) {
905
            return;
906
        }
907
        ComboBoxModel model = this.ddnLogicalOperators.getModel();
908
        for (int i = 0; i < model.getSize(); i++) {
909
            LabeledValue modelValue = (LabeledValue) model.getElementAt(i);
910
            String value = (String) modelValue.getValue();
911
            if (StringUtils.equals(value, operator)) {
912
                this.ddnLogicalOperators.setSelectedIndex(i);
913
                break;
914
            }
915
        }
916 44829 omartinez
    }
917 47302 jjdelcerro
918
    public Object getValue() {
919
        return this.getValue(true);
920
    }
921 44262 jjdelcerro
922 47302 jjdelcerro
    public Object getValue(boolean coerce) {
923 45326 omartinez
        final Field field = (Field) this.ddnFields.getSelectedItem();
924
        if (field == null) {
925
            return null;
926
        }
927
        Object v;
928
        if (this.dateController == null) {
929
            v = this.cboValue.getSelectedItem();
930
        } else {
931 46941 fdiaz
            if(this.dateController.isValid()) {
932
                v = this.dateController.get();
933
            } else {
934
                v = null;
935
            }
936 45326 omartinez
        }
937
        if (v == null) {
938
            return null;
939
        }
940
        if (v instanceof LabeledValue) {
941
            v = ((LabeledValue) v).getValue();
942 45793 jjdelcerro
            if (v == null || v == LOAD_MORE_ELEMENTS) {
943 45326 omartinez
                return null;
944
            }
945
        }
946
        if (v instanceof CharSequence) {
947
            if (StringUtils.isBlank((CharSequence) v)) {
948
                return null;
949
            }
950
        }
951 47302 jjdelcerro
        if( coerce ) {
952
            Coercion coercion = field.getDescriptor().getDataType().getCoercion();
953
            try {
954
                return coercion.coerce(v);
955
            } catch (CoercionException ex) {
956
                return null;
957
            }
958 45326 omartinez
        }
959 47302 jjdelcerro
        return v;
960
961 44829 omartinez
    }
962 44748 jjdelcerro
963 45274 omartinez
    public void setValue(Object value) {
964
        //this.cboValue.setSelectedItem(value);
965
        SwingUtilities.invokeLater(new Runnable() {
966
            @Override
967
            public void run() {
968 45326 omartinez
                DefaultComboBoxModel model = (DefaultComboBoxModel) cboValue.getModel();
969
                for (int i = 0; i < model.getSize(); i++) {
970
                    Object item = model.getElementAt(i);
971 45274 omartinez
                    if (item.equals(value)) {
972 45326 omartinez
                        cboValue.setSelectedIndex(i);
973
                        valueAssigned = value;
974
                        return;
975
                    }
976 45274 omartinez
                }
977 46517 fdiaz
                // si no lo encuentra en el modelo lo a?ade
978 45326 omartinez
                final Field field = (Field) ddnFields.getSelectedItem();
979 47264 jjdelcerro
                if (field != null) {
980 45326 omartinez
                    LabeledValue[] availableValues = field.getDescriptor().getAvailableValues();
981
                    Map<String, String> availableValuesMap = new HashMap<>();
982
                    if (availableValues != null) {
983
                        for (LabeledValue availableValue : availableValues) {
984
                            availableValuesMap.put(
985
                                    Objects.toString(availableValue.getValue()),
986
                                    availableValue.getLabel()
987
                            );
988
                        }
989
                    }
990
                    String key;
991
                    if (value instanceof Date) {
992
                        DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
993
                        df.setLenient(false);
994
                        key = df.format(value);
995
                    } else {
996
                        key = Objects.toString(value);
997
                    }
998
                    String label = availableValuesMap.getOrDefault(key, key);
999
                    LabeledValueImpl newItem = new LabeledValueImpl(label, value);
1000
                    model.addElement(newItem);
1001
                    cboValue.setSelectedItem(newItem);
1002
                    valueAssigned = newItem;
1003
                }
1004 45274 omartinez
            }
1005
        });
1006
    }
1007 44855 jjdelcerro
1008 45326 omartinez
    private Field getCurrentField() {
1009
        final Field field = (Field) this.ddnFields.getSelectedItem();
1010
        return field;
1011 44262 jjdelcerro
    }
1012
1013 45326 omartinez
    public int setAttribute(String name) {
1014 44829 omartinez
        ComboBoxModel<Field> model = this.ddnFields.getModel();
1015
        for (int i = 0; i < model.getSize(); i++) {
1016 45326 omartinez
            Field x = model.getElementAt(i);
1017
            if (StringUtils.equalsIgnoreCase(name, x.getValue())) {
1018
                this.setAttribute(i);
1019
                return i;
1020
            }
1021 44829 omartinez
        }
1022 45326 omartinez
        this.setAttribute(-1);
1023
        return -1;
1024
    }
1025 44842 omartinez
1026 45326 omartinez
    public void setAttribute(int index) {
1027
        try {
1028
            this.ddnFields.setSelectedIndex(index);
1029
        } catch (Exception ex) {
1030
            this.ddnFields.setSelectedIndex(-1);
1031 44829 omartinez
        }
1032 45326 omartinez
        doUpdateValuesList();
1033 44259 jjdelcerro
    }
1034 44842 omartinez
1035 45326 omartinez
    public int setAttributePath(String[][] pathNames) {
1036
        // [[attributeName, storeName],...]
1037
        try {
1038
            if (pathNames.length == 1) {
1039
                String[] path = pathNames[pathNames.length - 1];
1040
                String name = path[0];
1041
                int index = this.setAttribute(name);
1042
                if (index == -1) {
1043
                    try {
1044 46536 fdiaz
                        FeatureAttributeDescriptor attrDescriptor = store.getDefaultFeatureType().getAttributeDescriptorFromAll(name);
1045 45326 omartinez
                        if (attrDescriptor == null) {
1046 46536 fdiaz
                            FeatureQuery query = this.parameters.getQuery();
1047
                            if(query != null){
1048
                                attrDescriptor = query.getExtraColumns().get(name);
1049
                            }
1050
                        }
1051
                        if (attrDescriptor == null) {
1052 45326 omartinez
                            I18nManager i18n = ToolsLocator.getI18nManager();
1053
                            ThreadSafeDialogsManager dialogManager = ToolsSwingLocator.getThreadSafeDialogsManager();
1054
                            dialogManager.messageDialog(
1055
                                    i18n.getTranslation("_It_is_not_supported_to_search_through_this_field") + ":\n " + name + "\n"
1056
                                    + i18n.getTranslation("_Field_not_found_in_this_table"),
1057
                                    "_Warning",
1058
                                    JOptionPane.WARNING_MESSAGE
1059
                            );
1060
                            this.cboValue.setModel(new DefaultComboBoxModel());
1061
                        } else {
1062 46536 fdiaz
                            FeatureAttributeDescriptor[] attributePath = new FeatureAttributeDescriptor[]{attrDescriptor};
1063
                            doAddAndSelect(store, attrDescriptor, attributePath);
1064 45326 omartinez
                        }
1065
                    } catch (Exception ex) {
1066
                        LOGGER.warn("Not able to set single path into controller", ex);
1067
                        return -1;
1068
                    }
1069
                }
1070
                return index;
1071
            } else {
1072
                ComboBoxModel<Field> model = this.ddnFields.getModel();
1073
                String[] singleArrayPathNameDescriptors = new String[pathNames.length];
1074
                for (int i = 0; i < pathNames.length; i++) {
1075
                    singleArrayPathNameDescriptors[i] = pathNames[i][0];
1076
                }
1077
                // check the drop
1078
                for (int i = 0; i < model.getSize(); i++) {
1079
                    Field x = model.getElementAt(i);
1080
                    String[] arrayDescriptors = new String[x.getPath().length];
1081
                    FeatureAttributeDescriptor[] path = x.getPath();
1082
                    for (int j = 0; j < path.length; j++) {
1083
                        arrayDescriptors[j] = path[j].getName();
1084
                    }
1085
                    if (Arrays.equals(singleArrayPathNameDescriptors, arrayDescriptors)) {
1086
                        this.setAttribute(i);
1087
                        return i;
1088
                    }
1089
                }
1090
                // if not, addit to the drop
1091
                DataManager dataManager = DALLocator.getDataManager();
1092
                String tableName = pathNames[pathNames.length - 1][1]; // del ultimo path, coger el nombre tabla
1093
                FeatureStore theStore = (FeatureStore) dataManager.getStoresRepository().getStore(tableName);
1094
                String attributeName = pathNames[pathNames.length - 1][0]; // del ultimo path, coger el nombre attribute
1095
                if (theStore != null) {
1096
                    FeatureAttributeDescriptor attr;
1097
                    try {
1098
                        attr = theStore.getDefaultFeatureType().getAttributeDescriptor(attributeName);
1099
                        FeatureAttributeDescriptor[] attributePath = new FeatureAttributeDescriptor[2];
1100
                        String firstAttrName = pathNames[0][0];
1101
                        FeatureAttributeDescriptor firstAttr = store.getDefaultFeatureType().getAttributeDescriptor(firstAttrName);
1102
                        attributePath[0] = firstAttr;
1103 44842 omartinez
1104 45326 omartinez
                        attributePath[1] = attr;
1105
                        doAddAndSelect(theStore, attr, attributePath);
1106
                        return SIZE_ORDERED_ATTRIBUTES - 1;
1107
                    } catch (Exception ex) {
1108
                        LOGGER.warn("Not able to set foreign path into controller", ex);
1109
                    }
1110 44842 omartinez
1111 45326 omartinez
                }
1112
1113
            }
1114
        } catch (Exception ex) {
1115
            LOGGER.warn("Controller not set.", ex);
1116 44829 omartinez
        }
1117 45326 omartinez
        this.setAttribute(-1);
1118
        return -1;
1119 44748 jjdelcerro
    }
1120 44842 omartinez
1121 45326 omartinez
    private boolean isTheSameStore(DataStore store1, DataStore store2) {
1122
        String store1FullName = store1.getFullName();
1123
        String store2FullName = store2.getFullName();
1124
        return StringUtils.equalsIgnoreCase(store1FullName, store2FullName);
1125 44829 omartinez
    }
1126 45326 omartinez
1127
    private String getPrimaryKeyName(FeatureStore store) {
1128
        try {
1129
            FeatureAttributeDescriptor[] pk = store.getDefaultFeatureType().getPrimaryKey();
1130
            if (pk == null || pk.length != 1) {
1131
                return null;
1132
            }
1133
            return pk[0].getName();
1134
        } catch (DataException ex) {
1135
            return null;
1136
        }
1137 44292 jjdelcerro
    }
1138 45326 omartinez
1139
    private String getForeingKeyName(FeatureStore store, FeatureStore foreingStore) {
1140
        try {
1141
            for (FeatureAttributeDescriptor descriptor : store.getDefaultFeatureType()) {
1142
                if (descriptor.isForeingKey()) {
1143
                    ForeingKey foreingKey = descriptor.getForeingKey();
1144
                    if (isTheSameStore(foreingStore, foreingKey.getFeatureStore(null))) {
1145
                        return descriptor.getName();
1146
                    }
1147
                }
1148
            }
1149
        } catch (DataException ex) {
1150
            return null;
1151
        }
1152
        return null;
1153 44259 jjdelcerro
    }
1154 45326 omartinez
1155
    public boolean isValid(StringBuilder message) {
1156 44829 omartinez
        try {
1157 45326 omartinez
            Object value = this.getValue();
1158
            if (value == null) {
1159
                return true;
1160
            }
1161
            Field field = this.getCurrentField();
1162
            if (field == null) {
1163
                return true;
1164
            }
1165
            if (field.getPath().length > 2) {
1166
                message.append("Invalid field '").append(field.getLabel()).append("'.\n");
1167
                return false;
1168
            }
1169
            FeatureAttributeDescriptor descriptor = field.getDescriptor();
1170
            switch (this.getRelationalOperator()) {
1171
                case ExpressionBuilder.OPERATOR_EQ:
1172
                case ExpressionBuilder.OPERATOR_NE:
1173
                case ExpressionBuilder.OPERATOR_GT:
1174
                case ExpressionBuilder.OPERATOR_GE:
1175
                case ExpressionBuilder.OPERATOR_LT:
1176
                case ExpressionBuilder.OPERATOR_LE:
1177
        try {
1178
                    descriptor.getDataType().coerce(value);
1179
                } catch (CoercionException ex) {
1180
                    message.append("Invalid value '")
1181
                            .append(Objects.toString(value))
1182
                            .append("' for field '")
1183
                            .append(descriptor.getLabel())
1184
                            .append("'.");
1185
                    message.append("\n");
1186
                    message.append(ex.getMessage());
1187
                    message.append("\n");
1188
                    return false;
1189
                }
1190
                break;
1191 44829 omartinez
1192 45326 omartinez
                default:
1193
                case ExpressionBuilder.OPERATOR_ILIKE:
1194 46846 jjdelcerro
                case OPERATOR_CONTAINS:
1195 45326 omartinez
                    break;
1196
            }
1197
            return true;
1198
        } catch (Exception ex) {
1199
            message.append("Invalid values '").append(ex.toString());
1200
            return false;
1201
        }
1202 44748 jjdelcerro
    }
1203 44262 jjdelcerro
1204 45326 omartinez
    public ExpressionBuilder.Value getFilter() {
1205 47275 jjdelcerro
        StringBuilder warns = new StringBuilder();
1206
        return this.getFilter(warns);
1207
    }
1208
1209
    public ExpressionBuilder.Value getFilter(StringBuilder warnings) {
1210 45326 omartinez
        ExpressionBuilder.Value filter = null;
1211 44748 jjdelcerro
1212 45326 omartinez
        Field field = this.getCurrentField();
1213
        if (field == null) {
1214
            return null;
1215
        }
1216
        if (field.getPath().length > 2) {
1217
            // No soportado
1218 47275 jjdelcerro
            warnings.append("Lookups are only supported on directly related tables.");
1219 45326 omartinez
            return null;
1220
        }
1221
        DataManager dataManager = DALLocator.getDataManager();
1222
        DALExpressionBuilder builder = dataManager.createDALExpressionBuilder();
1223
        FeatureAttributeDescriptor parentDescriptor = field.getParentDescriptor();
1224
        FeatureAttributeDescriptor descriptor = field.getDescriptor();
1225 47264 jjdelcerro
1226
        switch(descriptor.getType()) {
1227
            case DataTypes.GEOMETRY:
1228 47275 jjdelcerro
                filter = this.createGeometryFilter(builder, parentDescriptor, descriptor, field, warnings);
1229 47264 jjdelcerro
                if( filter == null ) {
1230
                    return null;
1231
                }
1232
                filter = builder.expression().group(filter);
1233
                return filter;
1234
            case DataTypes.DATE:
1235
            default:
1236
        }
1237 47302 jjdelcerro
        Object value = null;
1238 45326 omartinez
        ExpressionBuilder.Constant value_constant = null;
1239 44262 jjdelcerro
1240 46846 jjdelcerro
        String operator = this.getRelationalOperator();
1241
        switch (operator) {
1242 45331 omartinez
            case ExpressionBuilder.OPERATOR_IS_NULL:
1243 47302 jjdelcerro
                value = this.getValue();
1244 45331 omartinez
                filter = getFilterForOperatorNull(parentDescriptor, descriptor, builder, field);
1245
                return filter;
1246
            case ExpressionBuilder.OPERATOR_IS_NOT_NULL:
1247 47302 jjdelcerro
                value = this.getValue();
1248 45331 omartinez
                filter = getFilterForOperatorNotNull(parentDescriptor, descriptor, builder, field);
1249
                return filter;
1250 45326 omartinez
            case ExpressionBuilder.OPERATOR_EQ:
1251
            case ExpressionBuilder.OPERATOR_NE:
1252
            case ExpressionBuilder.OPERATOR_GT:
1253
            case ExpressionBuilder.OPERATOR_GE:
1254
            case ExpressionBuilder.OPERATOR_LT:
1255
            case ExpressionBuilder.OPERATOR_LE:
1256 47302 jjdelcerro
                value = this.getValue();
1257
                if (value == null ) {
1258
                    return null;
1259
                }
1260 47264 jjdelcerro
                try {
1261
                    value_constant = builder.expression().constant(
1262
                            descriptor.getDataType().coerce(value)
1263
                    );
1264
                } catch (CoercionException ex) {
1265
                    return null;
1266
                }
1267
                break;
1268 44262 jjdelcerro
1269 46926 fdiaz
            case ExpressionBuilder.OPERATOR_ILIKE:
1270 47302 jjdelcerro
                value = this.getValue(false);
1271
                if (value == null ) {
1272
                    return null;
1273
                }
1274 45326 omartinez
                value_constant = builder.expression().constant(value);
1275
                break;
1276 46846 jjdelcerro
            default:
1277
            case OPERATOR_CONTAINS:
1278 47302 jjdelcerro
                value = this.getValue(false);
1279
                if (value == null ) {
1280
                    return null;
1281
                }
1282 46926 fdiaz
                value_constant = builder.expression().constant("%" + value + "%");
1283 46846 jjdelcerro
                operator = ExpressionBuilder.OPERATOR_ILIKE;
1284 47264 jjdelcerro
                break;
1285 45326 omartinez
        }
1286 44750 jjdelcerro
1287 46926 fdiaz
        ExpressionBuilder.Value fieldOp = null;
1288 45326 omartinez
        if (parentDescriptor == null) {
1289 46926 fdiaz
            fieldOp = builder.expression().column(this.store.getName(), descriptor.getName());
1290
            if (StringUtils.equalsIgnoreCase(operator, ExpressionBuilder.OPERATOR_ILIKE) && descriptor.getType() != DataTypes.STRING) {
1291 47320 fdiaz
                fieldOp = builder.expression().cast(fieldOp,DataTypes.STRING);
1292 46926 fdiaz
            }
1293
1294
1295 45331 omartinez
            // Se busca en campos de la misma tabla.
1296
            filter = builder.expression().binaryOperator(
1297 46846 jjdelcerro
                    operator,
1298 46926 fdiaz
                    fieldOp,
1299 45331 omartinez
                    value_constant
1300
            );
1301 44750 jjdelcerro
1302 45331 omartinez
            ExpressionBuilder.Value nullValue = builder.expression().column(this.store.getName(), descriptor.getName());
1303
            filter = addNullBehavior(builder, filter, nullValue);
1304 44750 jjdelcerro
1305 45326 omartinez
        } else {
1306
            // Se busca en campos de una tabla relacionada.
1307
            switch (parentDescriptor.getRelationType()) {
1308
                case DynField.RELATION_TYPE_COLLABORATION:
1309
                case DynField.RELATION_TYPE_IDENTITY:
1310 46926 fdiaz
                    fieldOp = builder.foreing_value(
1311
                            parentDescriptor.getName(),
1312
                            descriptor.getName()
1313
                    );
1314
                    if (StringUtils.equalsIgnoreCase(operator, ExpressionBuilder.OPERATOR_ILIKE) && descriptor.getType() != DataTypes.STRING) {
1315 47320 fdiaz
                        fieldOp = builder.expression().cast(fieldOp,DataTypes.STRING);
1316 46926 fdiaz
                    }
1317
1318 45331 omartinez
                    filter = builder.expression().binaryOperator(
1319 46846 jjdelcerro
                            operator,
1320 46926 fdiaz
                            fieldOp,
1321 45331 omartinez
                            value_constant
1322
                    );
1323
                    ExpressionBuilder.Value nullValue = builder.foreing_value(
1324
                            parentDescriptor.getName(),
1325
                            descriptor.getName()
1326
                    );
1327
                    filter = addNullBehavior(builder, filter, nullValue);
1328 45326 omartinez
                    break;
1329 44842 omartinez
1330 45326 omartinez
                case DynField.RELATION_TYPE_AGGREGATE:
1331
                case DynField.RELATION_TYPE_COMPOSITION:
1332
                    ExpressionBuilder.Value op_composition = null;
1333 46926 fdiaz
                    fieldOp = builder.expression().column(
1334
                            field.getFeatureStore().getName(),
1335
                            descriptor.getName()
1336
                    );
1337
                    if (StringUtils.equalsIgnoreCase(operator, ExpressionBuilder.OPERATOR_ILIKE) && descriptor.getType() != DataTypes.STRING) {
1338 47320 fdiaz
                        fieldOp = builder.expression().cast(fieldOp,DataTypes.STRING);
1339 46926 fdiaz
                    }
1340 45331 omartinez
                    op_composition = builder.expression().binaryOperator(
1341 46846 jjdelcerro
                            operator,
1342 46926 fdiaz
                            fieldOp,
1343 45331 omartinez
                            value_constant
1344
                    );
1345
                    ExpressionBuilder.Value null_value = builder.expression().column(
1346
                            field.getFeatureStore().getName(),
1347
                            descriptor.getName()
1348
                    );
1349 45352 omartinez
                    op_composition = addNullBehavior(builder, op_composition, null_value);
1350 44842 omartinez
1351 46517 fdiaz
                    filter = buildExists(builder, field, op_composition);
1352 45326 omartinez
                    break;
1353
            }
1354
        }
1355 45331 omartinez
1356 45326 omartinez
        filter = builder.expression().group(filter);
1357
        return filter;
1358 44855 jjdelcerro
    }
1359 44767 jjdelcerro
1360 46517 fdiaz
    private ExpressionBuilder.Value buildExists(DALExpressionBuilder builder, Field field, ExpressionBuilder.Value op_composition) {
1361
        ExpressionBuilder.Value filter;
1362
        SQLBuilder.SelectBuilder select = builder.select();
1363
        select.from().table().name(field.getFeatureStore().getName());
1364
        //select.column().name(parentDescriptor.getFeatureType().getPrimaryKey()[0].getName());
1365
        select.column().value(builder.expression().constant(1));
1366
        select.limit(1);
1367
        select.where().value(
1368
                builder.expression().and(
1369
                        builder.expression().eq(
1370
                                builder.expression().column(
1371
                                        field.getFeatureStore().getName(),
1372
                                        getForeingKeyName(field.getFeatureStore(), this.store)
1373
                                ),
1374
                                builder.expression().column(
1375
                                        this.store.getName(),
1376
                                        getPrimaryKeyName(this.store)
1377
                                )
1378
                        ),
1379
                        op_composition
1380
                )
1381
        );
1382
        filter = builder.exists(select);
1383
        return filter;
1384
    }
1385
1386 45326 omartinez
    public JsonObject toJson() {
1387
        JsonObjectBuilder fieldBuilder = Json.createObjectBuilder();
1388 44750 jjdelcerro
1389 45326 omartinez
        JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
1390 46536 fdiaz
        Field currentField = this.getCurrentField();
1391
//        if(currentField == null){
1392
//            return null;
1393
//        }
1394
        FeatureAttributeDescriptor[] path = currentField.getPath();
1395 46358 fdiaz
        for (int i = 0; i < path.length; i++) {
1396
            FeatureAttributeDescriptor featureAttributeDescriptor = path[i];
1397 45326 omartinez
            JsonArrayBuilder pathArray = Json.createArrayBuilder();
1398 44767 jjdelcerro
1399 45326 omartinez
            //first value: name field
1400
            String fieldName = featureAttributeDescriptor.getName();
1401
            pathArray.add(fieldName);
1402
            //second value: name store
1403 46358 fdiaz
            if(i==0){
1404
                pathArray.add(this.store.getName());
1405
            } else {
1406
                FeatureType featureType = featureAttributeDescriptor.getFeatureType();
1407
                String storeName = featureType.getStore().getName();
1408
                pathArray.add(storeName);
1409 47784 jjdelcerro
                }
1410 47264 jjdelcerro
            arrayBuilder.add(pathArray);
1411 45326 omartinez
        }
1412
        String relational = this.getRelationalOperator();
1413 47302 jjdelcerro
        Object value = this.getValue(false);
1414 45326 omartinez
        String strValue = DataTypeUtils.toString(value);
1415
        String logical = this.getLogicalOperator();
1416
1417 47264 jjdelcerro
        fieldBuilder.add("fieldPath", arrayBuilder);
1418 45326 omartinez
        fieldBuilder.add("relational", relational);
1419
        if (!StringUtils.isEmpty(strValue)) {
1420
            fieldBuilder.add("strValue", strValue);
1421
        }
1422
        if (!StringUtils.isEmpty(logical)) {
1423
            fieldBuilder.add("logical", logical);
1424
        }
1425
        int nullBehavior = this.getNullBehavior();
1426
        fieldBuilder.add("nullBehavior", nullBehavior);
1427 47264 jjdelcerro
1428
        fieldBuilder.add("geometryOperandMode", this.geometryOperandMode);
1429 47672 jjdelcerro
        fieldBuilder.add("geometryOperandStoreName", this.geometryOperandStoreId);
1430 47264 jjdelcerro
        fieldBuilder.add("geometryOperandConstant", this.geometryOperandConstant);
1431 47564 jjdelcerro
        fieldBuilder.add("useBox2dInGeometryOperand", this.useBox2dInGeometryOperand);
1432 45326 omartinez
        return fieldBuilder.build();
1433 44855 jjdelcerro
    }
1434 46501 jjdelcerro
1435
    public void put(SearchParameters params, int index) {
1436
        this.parameters = params;
1437
        Map<String, JsonObject> values = params.getValues();
1438
        if( values == null ) {
1439
            return;
1440
        }
1441
        JsonObject panelState = values.getOrDefault(PANEL_NAME, null);
1442
        if( panelState == null ) {
1443
            return;
1444
        }
1445
        String name = DataTypeUtils.toString(index);
1446
        this.fromJson(panelState.getJsonObject(name));
1447
    }
1448
1449 45326 omartinez
    public void fromJson(JsonObject jsonState) {
1450
        if (jsonState == null) {
1451
            return;
1452
        }
1453 44767 jjdelcerro
1454 45326 omartinez
        JsonArray fieldPath = jsonState.getJsonArray("fieldPath");
1455
1456
        // array of arrays
1457
        String[][] arrayNew = new String[fieldPath.size()][2];
1458
        for (int i = 0; i < fieldPath.size(); i++) {
1459
            String[] arrayField = new String[2];
1460
            arrayField[0] = fieldPath.getJsonArray(i).getString(0);
1461
            arrayField[1] = fieldPath.getJsonArray(i).getString(1);
1462
            arrayNew[i] = arrayField;
1463
        }
1464
        this.setAttributePath(arrayNew);  //usar el doAddAndSelect
1465
1466
        String relational = jsonState.getString("relational");
1467
        this.setRelationalOperator(relational);
1468
1469
        if (jsonState.containsKey("strValue")) {
1470
            String strValue = jsonState.getString("strValue");
1471 45280 omartinez
//        SwingUtilities.invokeLater(new Runnable() {
1472
//            @Override
1473
//            public void run() {
1474 45326 omartinez
            setValue(strValue);
1475 45280 omartinez
//            }
1476
//        });
1477 45326 omartinez
        }
1478
        if (jsonState.containsKey("logical")) {
1479
            String logical = jsonState.getString("logical");
1480
            this.setLogicalOperator(logical);
1481
        }
1482
        if (jsonState.containsKey("nullBehavior")) {
1483
            int nullBehavior = jsonState.getInt("nullBehavior");
1484
            this.setNullBehavior(nullBehavior);
1485
        }
1486
1487 47264 jjdelcerro
        this.geometryOperandMode = jsonState.getInt("geometryOperandMode", GEOM_OPERAND_MODE_CLIPBOARD);
1488 47672 jjdelcerro
        this.geometryOperandStoreId = jsonState.getString("geometryOperandStoreName", null);
1489 47264 jjdelcerro
        this.geometryOperandConstant = (Geometry) Json.toObject(jsonState,"geometryOperandConstant");
1490 47564 jjdelcerro
        this.useBox2dInGeometryOperand = jsonState.getBoolean("geometryOperandStoreName", false);
1491 44748 jjdelcerro
    }
1492 45326 omartinez
1493
    public void setUpdateValuesLimits(int limit, int featuresLimit) {
1494
        this.updateValuesTimeLimit = limit;
1495
        this.updateValuesFeaturesLimit = featuresLimit;
1496
        doUpdateValuesList();
1497 44855 jjdelcerro
    }
1498
1499 45326 omartinez
    public int getNullBehavior() {
1500
        return (int) ((LabeledValue) this.ddnNullBehavior.getSelectedItem()).getValue();
1501
    }
1502 45331 omartinez
1503 45326 omartinez
    public int setNullBehavior(int nullBehaviorValue) {
1504 45331 omartinez
        int n = 0;
1505 45326 omartinez
        for (LabeledValue nullBehavior : nullBehaviors) {
1506
            int toInt = (int) nullBehavior.getValue();
1507
            if (nullBehaviorValue == toInt) {
1508
                break;
1509
            }
1510
            n++;
1511
        }
1512
        if (this.nullBehaviors.length <= n) {
1513
            return -1;
1514
        }
1515
        this.ddnNullBehavior.setSelectedIndex(n);
1516
        return n;
1517
    }
1518 45331 omartinez
1519
    private ExpressionBuilder.Value addNullBehavior(DALExpressionBuilder builder, ExpressionBuilder.Value filter, ExpressionBuilder.Value nullValue) {
1520
        if (this.getRelationalOperator() != ExpressionBuilder.OPERATOR_IS_NULL && this.getRelationalOperator() != ExpressionBuilder.OPERATOR_IS_NOT_NULL) {
1521
            if (this.getNullBehavior() == NULL_AS_TRUE) {
1522
                ExpressionBuilder.Function null_function = builder.expression().is_null(nullValue);
1523
                filter = builder.expression().or(null_function, filter);
1524
            } else if (this.getNullBehavior() == NULL_AS_FALSE) {
1525
                ExpressionBuilder.Function null_function = builder.expression().not_is_null(nullValue);
1526
                filter = builder.expression().and(null_function, filter);
1527
            }
1528
        }
1529
        return filter;
1530
    }
1531
1532
    private ExpressionBuilder.Value getFilterForOperatorNull(
1533
            FeatureAttributeDescriptor parentDescriptor,
1534
            FeatureAttributeDescriptor descriptor,
1535
            DALExpressionBuilder builder,
1536
            Field field) {
1537
1538
        ExpressionBuilder.Value filter = null;
1539
        if (parentDescriptor == null) {
1540
            filter = builder.expression().is_null(builder.expression().column(this.store.getName(), descriptor.getName()));
1541
        } else {
1542
            // Se busca en campos de una tabla relacionada.
1543
            switch (parentDescriptor.getRelationType()) {
1544
                case DynField.RELATION_TYPE_COLLABORATION:
1545
                case DynField.RELATION_TYPE_IDENTITY:
1546
                    filter = builder.expression().is_null(builder.foreing_value(
1547
                            parentDescriptor.getName(),
1548
                            descriptor.getName()
1549
                    ));
1550 46699 fdiaz
                    break;
1551 45331 omartinez
                case DynField.RELATION_TYPE_AGGREGATE:
1552
                case DynField.RELATION_TYPE_COMPOSITION:
1553
                    ExpressionBuilder.Value op_composition = null;
1554
                    op_composition = builder.expression().is_null(builder.expression().column(
1555
                            field.getFeatureStore().getName(),
1556
                            descriptor.getName()
1557
                    ));
1558 46517 fdiaz
                    filter = buildExists(builder, field, op_composition);
1559 45331 omartinez
            }
1560
        }
1561
1562
        filter = builder.expression().group(filter);
1563
        return filter;
1564
    }
1565
1566
    private ExpressionBuilder.Value getFilterForOperatorNotNull(
1567
            FeatureAttributeDescriptor parentDescriptor,
1568
            FeatureAttributeDescriptor descriptor,
1569
            DALExpressionBuilder builder,
1570
            Field field) {
1571
1572
        ExpressionBuilder.Value filter = null;
1573
        if (parentDescriptor == null) {
1574
            filter = builder.expression().not_is_null(builder.expression().column(this.store.getName(), descriptor.getName()));
1575
        } else {
1576
            // Se busca en campos de una tabla relacionada.
1577
            switch (parentDescriptor.getRelationType()) {
1578
                case DynField.RELATION_TYPE_COLLABORATION:
1579
                case DynField.RELATION_TYPE_IDENTITY:
1580
                    filter = builder.expression().not_is_null(builder.foreing_value(
1581
                            parentDescriptor.getName(),
1582
                            descriptor.getName()
1583
                    ));
1584 46699 fdiaz
                    break;
1585 45331 omartinez
                case DynField.RELATION_TYPE_AGGREGATE:
1586
                case DynField.RELATION_TYPE_COMPOSITION:
1587
                    ExpressionBuilder.Value op_composition = null;
1588
                    op_composition = builder.expression().not_is_null(builder.expression().column(
1589
                            field.getFeatureStore().getName(),
1590
                            descriptor.getName()
1591
                    ));
1592
1593 46517 fdiaz
                    filter = buildExists(builder, field, op_composition);
1594 45331 omartinez
            }
1595
        }
1596
1597
        filter = builder.expression().group(filter);
1598
        return filter;
1599
    }
1600 47264 jjdelcerro
1601 47564 jjdelcerro
    private ExpressionBuilder.Value getFilterForOperatorIsNotValid(
1602
            FeatureAttributeDescriptor parentDescriptor,
1603
            FeatureAttributeDescriptor descriptor,
1604
            DALExpressionBuilder builder,
1605
            Field field) {
1606
1607
        ExpressionBuilder.Value filter = null;
1608
        if (parentDescriptor == null) {
1609
            filter = builder.expression().not(
1610
                    builder.expression().ST_IsValid(
1611
                            builder.expression().column(this.store.getName(), descriptor.getName())
1612
                    )
1613
            );
1614
        } else {
1615
            // Se busca en campos de una tabla relacionada.
1616
            switch (parentDescriptor.getRelationType()) {
1617
                case DynField.RELATION_TYPE_COLLABORATION:
1618
                case DynField.RELATION_TYPE_IDENTITY:
1619
                    filter = builder.expression().not(
1620
                        builder.expression().ST_IsValid(
1621
                            builder.foreing_value(
1622
                                parentDescriptor.getName(),
1623
                                descriptor.getName()
1624
                            )
1625
                        )
1626
                    );
1627
                    break;
1628
                case DynField.RELATION_TYPE_AGGREGATE:
1629
                case DynField.RELATION_TYPE_COMPOSITION:
1630
                    ExpressionBuilder.Value op_composition = null;
1631
                    op_composition = builder.expression().not(
1632
                        builder.expression().ST_IsValid(
1633
                            builder.expression().column(
1634
                                field.getFeatureStore().getName(),
1635
                                descriptor.getName()
1636
                            )
1637
                        )
1638
                    );
1639
1640
                    filter = buildExists(builder, field, op_composition);
1641
            }
1642
        }
1643
1644
        filter = builder.expression().group(filter);
1645
        return filter;
1646
    }
1647
1648
    private ExpressionBuilder.Value getFilterForOperatorIsValid(
1649
            FeatureAttributeDescriptor parentDescriptor,
1650
            FeatureAttributeDescriptor descriptor,
1651
            DALExpressionBuilder builder,
1652
            Field field) {
1653
1654
        ExpressionBuilder.Value filter = null;
1655
        if (parentDescriptor == null) {
1656
            filter =builder.expression().ST_IsValid(
1657
                builder.expression().column(this.store.getName(), descriptor.getName())
1658
            );
1659
        } else {
1660
            // Se busca en campos de una tabla relacionada.
1661
            switch (parentDescriptor.getRelationType()) {
1662
                case DynField.RELATION_TYPE_COLLABORATION:
1663
                case DynField.RELATION_TYPE_IDENTITY:
1664
                    filter = builder.expression().ST_IsValid(
1665
                            builder.foreing_value(
1666
                                parentDescriptor.getName(),
1667
                                descriptor.getName()
1668
                            )
1669
                    );
1670
                    break;
1671
                case DynField.RELATION_TYPE_AGGREGATE:
1672
                case DynField.RELATION_TYPE_COMPOSITION:
1673
                    ExpressionBuilder.Value op_composition = null;
1674
                    op_composition =
1675
                        builder.expression().ST_IsValid(
1676
                            builder.expression().column(
1677
                                field.getFeatureStore().getName(),
1678
                                descriptor.getName()
1679
                            )
1680
                    );
1681
1682
                    filter = buildExists(builder, field, op_composition);
1683
            }
1684
        }
1685
1686
        filter = builder.expression().group(filter);
1687
        return filter;
1688
    }
1689
1690 47275 jjdelcerro
    private ExpressionBuilder.Value createGeometryFilter(
1691
            DALExpressionBuilder builder,
1692
            FeatureAttributeDescriptor parentDescriptor,
1693
            FeatureAttributeDescriptor descriptor,
1694
            Field field,
1695
            StringBuilder warnings
1696
        ) {
1697 47264 jjdelcerro
        ExpressionBuilder.Value filter = null;
1698
1699
        if( parentDescriptor!=null ) {
1700
            return null; //FIXME
1701
        }
1702 47275 jjdelcerro
        Geometry geometry = this.getGeometryOperand(descriptor.getSRS(), warnings);
1703 47264 jjdelcerro
        String operator = this.getRelationalOperator();
1704
        switch (operator) {
1705
            case ExpressionBuilder.OPERATOR_IS_NULL:
1706
                filter = getFilterForOperatorNull(parentDescriptor, descriptor, builder, field);
1707 47275 jjdelcerro
                break;
1708 47264 jjdelcerro
            case ExpressionBuilder.OPERATOR_IS_NOT_NULL:
1709
                filter = getFilterForOperatorNotNull(parentDescriptor, descriptor, builder, field);
1710 47275 jjdelcerro
                break;
1711 47564 jjdelcerro
            case GeometryExpressionBuilder.FUNCTION_ST_ISVALID:
1712
                filter = getFilterForOperatorIsValid(parentDescriptor, descriptor, builder, field);
1713
                break;
1714
            case FUNCTION_ISNOTVALID:
1715
                filter = getFilterForOperatorIsNotValid(parentDescriptor, descriptor, builder, field);
1716
                break;
1717
1718
1719
            case FUNCTION_INTERSECTSWITHBBOX:
1720
                if( geometry==null ) {
1721
                    return null; // FIXME
1722
                }
1723
                filter = builder.expression().ST_Intersects(
1724
                        builder.expression().ST_Envelope(
1725
                            builder.expression().column(descriptor.getName())
1726
                        ),
1727
                        builder.expression().geometry(geometry)
1728
                );
1729
                break;
1730 47264 jjdelcerro
            case GeometryExpressionBuilder.FUNCTION_ST_CONTAINS:
1731
            case GeometryExpressionBuilder.FUNCTION_ST_COVERS:
1732
            case GeometryExpressionBuilder.FUNCTION_ST_COVEREDBY:
1733
            case GeometryExpressionBuilder.FUNCTION_ST_CROSSES:
1734
            case GeometryExpressionBuilder.FUNCTION_ST_DISJOINT:
1735
            case GeometryExpressionBuilder.FUNCTION_ST_EQUALS:
1736
            case GeometryExpressionBuilder.FUNCTION_ST_INTERSECTS:
1737 47274 jjdelcerro
            case GeometryExpressionBuilder.FUNCTION_ST_OVERLAPS:
1738
            case GeometryExpressionBuilder.FUNCTION_ST_WITHIN:
1739
            case GeometryExpressionBuilder.FUNCTION_ST_TOUCHES:
1740 47361 fdiaz
                if( geometry==null ) {
1741
                    return null; // FIXME
1742
                }
1743 47264 jjdelcerro
                filter = builder.expression().function(
1744
                        operator,
1745
                        builder.expression().column(descriptor.getName()),
1746
                        builder.expression().geometry(geometry)
1747
                );
1748 47275 jjdelcerro
                break;
1749 47264 jjdelcerro
            case GeometryExpressionBuilder.FUNCTION_ST_ISCLOSED:
1750
                filter = builder.expression().function(
1751
                        operator,
1752
                        builder.expression().column(descriptor.getName())
1753
                );
1754 47275 jjdelcerro
                break;
1755
            default:
1756
                return null;
1757 47264 jjdelcerro
        }
1758 47275 jjdelcerro
        if( filter!=null ) {
1759
            String s = filter.toString();
1760
            if( s.length()>10000 ) {
1761
                warnings.append("There are many selected geometries or they are very large.");
1762
                warnings.append("\n");
1763
            }
1764
        }
1765
        return filter;
1766 47264 jjdelcerro
    }
1767
1768 47275 jjdelcerro
    private Geometry getGeometryOperand(IProjection proj, StringBuilder warnings) {
1769 47264 jjdelcerro
        List<Geometry> geoms;
1770
        switch(this.geometryOperandMode) {
1771
            case GEOM_OPERAND_MODE_LAYER_SELECTION:
1772 47672 jjdelcerro
                geoms = this.getGeometryOperandFromLayerSelection(this.geometryOperandStoreId, warnings);
1773 47264 jjdelcerro
                break;
1774
            case GEOM_OPERAND_MODE_CONSTANT:
1775 47275 jjdelcerro
                geoms = this.getGeometryOperandConstant(proj, warnings);
1776 47264 jjdelcerro
                break;
1777
            case GEOM_OPERAND_MODE_CLIPBOARD:
1778 47275 jjdelcerro
                geoms = this.getGeometryOperandFromClipboard(proj, warnings);
1779
                break;
1780 47618 jjdelcerro
            case GEOM_OPERAND_MODE_CURRENT_BOUNDINGBOX:
1781
                geoms = this.getCurrentBoundingBoxGeometry(proj, warnings);
1782
                break;
1783 47275 jjdelcerro
            case GEOM_OPERAND_MODE_EMPTY:
1784 47264 jjdelcerro
            default:
1785 47275 jjdelcerro
                return null;
1786 47264 jjdelcerro
        }
1787
        if( geoms==null || geoms.isEmpty() ) {
1788
            return null;
1789
        }
1790
        if( geoms.size()==1 ) {
1791
            return geoms.get(0);
1792
        }
1793 47275 jjdelcerro
        Geometry geom = GeometryUtils.toAggregate(geoms, warnings);
1794 47274 jjdelcerro
        if( geom!=null && geom.getProjection()==null ) {
1795
            geom.setProjection(proj);
1796
        }
1797
        return geom;
1798 47264 jjdelcerro
    }
1799
1800 47275 jjdelcerro
    private List<Geometry> getGeometryOperandConstant(IProjection proj, StringBuilder warnings) {
1801 47264 jjdelcerro
        if( this.geometryOperandConstant==null ) {
1802 47275 jjdelcerro
            warnings.append("The geometry with which to operate has not been indicated");
1803
            warnings.append("\n");
1804 47264 jjdelcerro
            return null;
1805
        }
1806
        if( this.geometryOperandConstant.getProjection()==null ) {
1807
            this.geometryOperandConstant.setProjection(proj);
1808
        }
1809
        return Collections.singletonList(this.geometryOperandConstant);
1810
    }
1811
1812 47275 jjdelcerro
    private List<Geometry> getGeometryOperandFromClipboard(IProjection proj, StringBuilder warnings) {
1813 47264 jjdelcerro
        try {
1814
            ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
1815
1816
            String s = toolsSwingManager.getFromClipboard();
1817
            if( StringUtils.isBlank(s) ) {
1818 47275 jjdelcerro
                warnings.append("The clipboard is empty");
1819
                warnings.append("\n");
1820 47264 jjdelcerro
                return null;
1821
            }
1822
            List<Geometry> geom = GeometryUtils.extractFrom(s, proj);
1823 47275 jjdelcerro
            if( geom == null ) {
1824
                warnings.append("Can't locate geometries in clipboard");
1825
                warnings.append("\n");
1826
                return null;
1827
            }
1828 47264 jjdelcerro
            return geom;
1829
        } catch (Exception ex) {
1830
            LOGGER.warn("Can't get geometry value.", ex);
1831 47275 jjdelcerro
            warnings.append("Can't extract a geometry from clipboard");
1832
            warnings.append("\n(");
1833
            warnings.append(ex.getLocalizedMessage());
1834
            warnings.append(")\n");
1835 47264 jjdelcerro
            return null;
1836
        }
1837
    }
1838
1839 47672 jjdelcerro
    private synchronized List<Geometry> getGeometryOperandFromLayerSelection(String storeId, StringBuilder warnings) {
1840
        if( StringUtils.isBlank(storeId) ) {
1841 47264 jjdelcerro
            return null;
1842
        }
1843
        StoresRepository repo = null;
1844
        FeatureStore theStore = null;
1845
        try {
1846
            repo = DALLocator.getDataManager().getStoresRepository();
1847 47672 jjdelcerro
            theStore = (FeatureStore) repo.getStore(storeId);
1848 47264 jjdelcerro
            if( theStore == null ) {
1849 47275 jjdelcerro
                warnings.append("Table not found in project.");
1850
                warnings.append("\n");
1851 47264 jjdelcerro
                return null;
1852
            }
1853
            String geomAttrName = theStore.getDefaultFeatureTypeQuietly().getDefaultGeometryAttributeName();
1854
            if( StringUtils.isEmpty(geomAttrName) ) {
1855 47275 jjdelcerro
                warnings.append("The selected table can't have geometries");
1856
                warnings.append("\n");
1857 47264 jjdelcerro
                return null;
1858
            }
1859
            if( theStore.isFeatureSelectionEmpty() ) {
1860 47275 jjdelcerro
                warnings.append("The selection of the selected table is empty.");
1861
                warnings.append("\n");
1862 47264 jjdelcerro
                return null;
1863
            }
1864
            Iterator<FeatureReference> it = theStore.getFeatureSelectionQuietly().referenceIterator();
1865
            List<Geometry> geoms = new ArrayList<>();
1866
            for (Feature feature : theStore.getFeaturesIterable(it)) {
1867 47564 jjdelcerro
                if(  this.useBox2dInGeometryOperand ) {
1868
                    geoms.add(feature.getGeometry(geomAttrName).getEnvelope().getBox2D());
1869
                } else {
1870
                    geoms.add(feature.getGeometry(geomAttrName));
1871
                }
1872 47264 jjdelcerro
            }
1873
            return geoms;
1874
        } finally {
1875
            DisposeUtils.dispose(theStore);
1876
        }
1877
    }
1878
1879
    private void doSelectGeometryOperand() {
1880
        I18nManager i18n = ToolsLocator.getI18nManager();
1881
        WindowManager_v2 windowManager = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
1882
        SelectGeometryPanel panel = new SelectGeometryPanel();
1883
        Dialog dialog = windowManager.createDialog(
1884
                panel,
1885
                i18n.getTranslation("_Indicate_where_to_obtain_the_geometries"),
1886
                null,
1887
                WindowManager_v2.BUTTONS_OK_CANCEL
1888
        );
1889
        dialog.addActionListener((ActionEvent e) -> {
1890
            if( dialog.getAction()==WindowManager_v2.BUTTON_OK ) {
1891
                this.geometryOperandMode = panel.getMode();
1892
                this.geometryOperandConstant = panel.getGeometry();
1893 47672 jjdelcerro
                this.geometryOperandStoreId = panel.getStoreId();
1894 47564 jjdelcerro
                this.useBox2dInGeometryOperand = panel.useBox2dInGeometryOperand();
1895 47264 jjdelcerro
                doUpdateCurrentValue();
1896
            }
1897
        });
1898 47564 jjdelcerro
        panel.setMode(this.geometryOperandMode);
1899
        panel.setGeometry(this.geometryOperandConstant);
1900 47672 jjdelcerro
        panel.setStoreId(this.geometryOperandStoreId);
1901 47564 jjdelcerro
        panel.setUseBox2dInGeometryOperand(this.useBox2dInGeometryOperand);
1902
1903 47264 jjdelcerro
        dialog.show(WindowManager.MODE.DIALOG);
1904
    }
1905 47275 jjdelcerro
1906
    public String getWarnings() {
1907
        StringBuilder warns = new StringBuilder();
1908
        ExpressionBuilder.Value filter = this.getFilter(warns);
1909
        String s = warns.toString();
1910
        if( StringUtils.isBlank(s) ) {
1911
            return null;
1912
        }
1913
        return s;
1914
    }
1915 47618 jjdelcerro
    private List<Geometry> getCurrentBoundingBoxGeometry(IProjection proj, StringBuilder warnings) {
1916
        DataSwingManager dataSwingManager = DALSwingLocator.getDataSwingManager();
1917
        Supplier<Envelope> bbox = dataSwingManager.getCurrentBoundingBox();
1918
        if( bbox!=null ) {
1919
            Envelope env = bbox.get();
1920
            if( env != null && !env.isEmpty() && !env.isCollapsed() ) {
1921
                return Collections.singletonList(env.getGeometry());
1922
            }
1923
        }
1924
        return null;
1925
    }
1926
1927 44351 jjdelcerro
}