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

History | View | Annotate | Download (37.1 KB)

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

    
3
import java.awt.Cursor;
4
import java.awt.event.ActionEvent;
5
import java.awt.event.ItemEvent;
6
import java.awt.event.ItemListener;
7
import java.awt.event.MouseAdapter;
8
import java.awt.event.MouseEvent;
9
import java.text.DateFormat;
10
import java.util.ArrayList;
11
import java.util.Arrays;
12
import java.util.Date;
13
import java.util.HashMap;
14
import java.util.List;
15
import java.util.Locale;
16
import java.util.Map;
17
import java.util.Objects;
18
import javax.json.Json;
19
import javax.json.JsonArray;
20
import javax.json.JsonArrayBuilder;
21
import javax.json.JsonObject;
22
import javax.json.JsonObjectBuilder;
23
import javax.swing.ComboBoxModel;
24
import javax.swing.DefaultComboBoxModel;
25
import javax.swing.ImageIcon;
26
import javax.swing.JComboBox;
27
import javax.swing.JLabel;
28
import javax.swing.JOptionPane;
29
import javax.swing.SwingUtilities;
30
import javax.swing.text.JTextComponent;
31
import org.apache.commons.lang3.StringUtils;
32
import org.gvsig.expressionevaluator.ExpressionBuilder;
33
import org.gvsig.fmap.dal.DALLocator;
34
import org.gvsig.fmap.dal.DataManager;
35
import org.gvsig.fmap.dal.DataStore;
36
import org.gvsig.fmap.dal.complements.Search;
37
import org.gvsig.fmap.dal.exception.DataException;
38
import org.gvsig.fmap.dal.expressionevaluator.DALExpressionBuilder;
39
import org.gvsig.fmap.dal.feature.Feature;
40
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
41
import org.gvsig.fmap.dal.feature.FeatureQuery;
42
import org.gvsig.fmap.dal.feature.FeatureSet;
43
import org.gvsig.fmap.dal.feature.FeatureStore;
44
import org.gvsig.fmap.dal.feature.FeatureType;
45
import org.gvsig.fmap.dal.feature.ForeingKey;
46
import org.gvsig.fmap.dal.swing.impl.featuretype.DefaultFeatureAttributeSelectionPanel;
47
import static org.gvsig.fmap.dal.swing.impl.searchpanel.DefaultSearchPanel.getAttributeDescriptorLabel;
48
import org.gvsig.fmap.dal.swing.searchpanel.SearchParameters;
49
import org.gvsig.tools.ToolsLocator;
50
import org.gvsig.tools.dataTypes.Coercion;
51
import org.gvsig.tools.dataTypes.CoercionException;
52
import org.gvsig.tools.dataTypes.DataTypeUtils;
53
import org.gvsig.tools.dataTypes.DataTypes;
54
import org.gvsig.tools.dispose.DisposeUtils;
55
import org.gvsig.tools.dynobject.DynField;
56
import org.gvsig.tools.exception.BaseException;
57
import org.gvsig.tools.i18n.I18nManager;
58
import org.gvsig.tools.swing.api.DropDown;
59
import org.gvsig.tools.swing.api.ToolsSwingLocator;
60
import org.gvsig.tools.swing.api.ToolsSwingManager;
61
import org.gvsig.tools.swing.api.pickercontroller.DatePickerController;
62
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
63
import org.gvsig.tools.swing.api.windowmanager.Dialog;
64
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
65
import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2;
66
import org.gvsig.tools.swing.icontheme.IconTheme;
67
import org.gvsig.tools.util.LabeledValue;
68
import org.gvsig.tools.util.LabeledValueImpl;
69
import org.gvsig.tools.visitor.VisitCanceledException;
70
import org.gvsig.tools.visitor.Visitor;
71
import org.slf4j.Logger;
72
import org.slf4j.LoggerFactory;
73

    
74
/**
75
 *
76
 * @author jjdelcerro
77
 */
78
@SuppressWarnings("UseSpecificCatch")
79
public class SearchConditionFieldController {
80

    
81
  private static final Logger LOGGER = LoggerFactory.getLogger(SearchConditionFieldController.class);
82
  private static final Class LOAD_MORE_ELEMENTS = SearchConditionFieldController.class;
83
  private static class Field extends LabeledValueImpl<String> {
84

    
85
    FeatureAttributeDescriptor attrdesc;
86
    private final FeatureStore store;
87
    private final int presentationMode;
88
    private final boolean showStoreName;
89
    private final FeatureAttributeDescriptor[] path;
90

    
91
    public Field(FeatureAttributeDescriptor[] path, FeatureStore store, FeatureAttributeDescriptor attrdesc, int presentationMode) {
92
      this(path, store, attrdesc, presentationMode, false);
93
    }
94

    
95
    public Field(
96
            FeatureAttributeDescriptor[] path,
97
            FeatureStore store,
98
            FeatureAttributeDescriptor attrdesc,
99
            int presentationMode,
100
            boolean showStoreName
101
    ) {
102
      super(
103
              getAttributeDescriptorLabel(attrdesc, store.getName()),
104
              attrdesc.getName()
105
      );
106
      this.path = path;
107
      this.store = store;
108
      this.attrdesc = attrdesc;
109
      this.presentationMode = presentationMode;
110
      this.showStoreName = showStoreName;
111
    }
112

    
113
    public FeatureAttributeDescriptor[] getPath() {
114
      return this.path;
115
    }
116

    
117
    @Override
118
    public String getLabel() {
119
      String theLabel = getAttributeDescriptorLabel(attrdesc, showStoreName ? store.getName() : null);
120
      switch (this.presentationMode) {
121
        case Search.OrderedAttribute.TYPE_REGURAL:
122
          break;
123
        case Search.OrderedAttribute.TYPE_FAVORITE:
124
          theLabel = "<html><b>" + theLabel + "</b></html>";
125
          break;
126
        case Search.OrderedAttribute.TYPE_RECENT:
127
          theLabel = "<html><i><b>" + theLabel + "</b></i></html>";
128
          break;
129
      }
130
      return theLabel;
131
    }
132

    
133
    public FeatureAttributeDescriptor getParentDescriptor() {
134
      int l = this.path.length;
135
      if (l < 2) {
136
        return null;
137
      }
138
      return this.path[l - 2];
139
    }
140

    
141
    public FeatureAttributeDescriptor getDescriptor() {
142
      return this.attrdesc;
143
    }
144

    
145
    public FeatureStore getFeatureStore() {
146
      return this.store;
147
    }
148

    
149
  }
150

    
151
  private FeatureStore store;
152
  private SearchParameters parameters;
153
  private final JLabel lblFields;
154
  private final JLabel lblExtraFields;
155
  private final JLabel lblLogicalOperators;
156
  private final JLabel lblRelationalOperators;
157
  private final JComboBox cboValue;
158
  private Object valueAssigned = null;
159

    
160
  private DropDown ddnFields;
161
  private DropDown ddnLogicalOperators;
162
  private DropDown ddnRelationalOperators;
163

    
164
  private LabeledValue[] relationalOperators;
165
  private LabeledValue[] logicalOperators;
166
  private final int SIZE_ORDERED_ATTRIBUTES = 20;
167
  
168
  private DatePickerController dateController = null;
169
  
170
  
171
  private int updateValuesTimeLimit;
172
  private int updateValuesFeaturesLimit;
173
  private boolean canHasMoreElements;
174

    
175

    
176
  public SearchConditionFieldController(
177
          SearchParameters parameters,
178
          FeatureStore store,
179
          JLabel lblFields,
180
          JLabel lblExtraFields,
181
          JLabel lblRelationalOperators,
182
          JComboBox cboValue,
183
          JLabel lblLogicalOperators
184
  ) {
185
    this.parameters = parameters;
186
    this.store = store;
187
    this.lblFields = lblFields;
188
    this.lblExtraFields = lblExtraFields;
189
    this.lblRelationalOperators = lblRelationalOperators;
190
    this.cboValue = cboValue;
191
    this.lblLogicalOperators = lblLogicalOperators;
192
    this.updateValuesTimeLimit = 60;
193
    this.updateValuesFeaturesLimit = 1000;
194
    this.canHasMoreElements = false;
195
    this.initComponents();
196
  }
197

    
198
  public boolean isAValidRelationOperator(String name) {
199
    for (LabeledValue relationalOperator : relationalOperators) {
200
      if (StringUtils.equalsIgnoreCase(name, (CharSequence) relationalOperator.getValue())) {
201
        return true;
202
      }
203
    }
204
    return false;
205
  }
206

    
207
  private void initComponents() {
208
    try {
209
      I18nManager i18n = ToolsLocator.getI18nManager();
210
      ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
211

    
212
      relationalOperators = new LabeledValue[]{
213
        new LabeledValueImpl(i18n.getTranslation("_Equals_to"), ExpressionBuilder.OPERATOR_EQ),
214
        new LabeledValueImpl(i18n.getTranslation("_Like_to"), ExpressionBuilder.OPERATOR_ILIKE),
215
        new LabeledValueImpl(i18n.getTranslation("_Not_equals_to"), ExpressionBuilder.OPERATOR_NE),
216
        new LabeledValueImpl(i18n.getTranslation("_Greater_than"), ExpressionBuilder.OPERATOR_GT),
217
        new LabeledValueImpl(i18n.getTranslation("_Greater_or_equal_to"), ExpressionBuilder.OPERATOR_GE),
218
        new LabeledValueImpl(i18n.getTranslation("_Less_than"), ExpressionBuilder.OPERATOR_LT),
219
        new LabeledValueImpl(i18n.getTranslation("_Less_or_equal_to"), ExpressionBuilder.OPERATOR_LE)
220
      };
221

    
222
      logicalOperators = new LabeledValue[]{
223
        new LabeledValueImpl(i18n.getTranslation("_Or"), ExpressionBuilder.OPERATOR_OR),
224
        new LabeledValueImpl(i18n.getTranslation("_And"), ExpressionBuilder.OPERATOR_AND)
225
      };
226

    
227
      this.lblExtraFields.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
228

    
229
      this.ddnFields = toolsSwingManager.createDropDown(lblFields);
230
      this.ddnFields.setVisibleDropdownArrow(false);
231
      this.ddnRelationalOperators = toolsSwingManager.createDropDown(lblRelationalOperators);
232
      this.ddnRelationalOperators.setVisibleDropdownArrow(false);
233
      if (lblLogicalOperators != null) {
234
        this.ddnLogicalOperators = toolsSwingManager.createDropDown(lblLogicalOperators);
235
        this.ddnLogicalOperators.setVisibleDropdownArrow(false);
236
      }
237

    
238
      DefaultComboBoxModel modelRelationalOperators = new DefaultComboBoxModel();
239
      for (LabeledValue op : relationalOperators) {
240
        modelRelationalOperators.addElement(op);
241
      }
242
      this.ddnRelationalOperators.setModel(modelRelationalOperators);
243

    
244
      if (this.ddnLogicalOperators != null) {
245
        DefaultComboBoxModel modelLogicalOperators = new DefaultComboBoxModel();
246
        for (LabeledValue op : logicalOperators) {
247
          modelLogicalOperators.addElement(op);
248
        }
249
        this.ddnLogicalOperators.setModel(modelLogicalOperators);
250
      }
251
      FeatureType featureType = parameters.getFeatureType(store);
252
      Search search = (Search) ToolsLocator.getComplementsManager().get(
253
              Search.COMPLEMENT_MANE, featureType
254
      );
255
      List<Search.OrderedAttribute> orderedAttributes = search.getOrderedAttributes(
256
              Search.BASIC_TYPES_FILTER,
257
              Search.STR_INT_LONG_LABEL_ORDER,
258
              SIZE_ORDERED_ATTRIBUTES
259
      );
260
      List<ImageIcon> icons = new ArrayList<>();
261
//            DataTypesManager dataTypeManager = ToolsLocator.getDataTypesManager();
262
      IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getCurrent();
263
      DefaultComboBoxModel model = new DefaultComboBoxModel();
264
      for (Search.OrderedAttribute attr : orderedAttributes) {
265
        FeatureAttributeDescriptor attrdesc = attr.getDescriptor();
266
        Field field = new Field(
267
                new FeatureAttributeDescriptor[]{attrdesc},
268
                this.store,
269
                attrdesc,
270
                attr.getType()
271
        );
272
        model.addElement(field);
273
        String iconName = attrdesc.getDataType().getIconName();
274
        if (iconTheme.exists(iconName)) {
275
          icons.add(iconTheme.get(iconName));
276
        } else {
277
          icons.add(null);
278
        }
279
      }
280
      this.ddnFields.setIcons(icons);
281
      this.ddnFields.setModel(model);
282
      this.ddnFields.addItemListener(new ItemListener() {
283
        @Override
284
        public void itemStateChanged(ItemEvent e) {
285
          if (e.getStateChange() == ItemEvent.SELECTED) {
286
            doUpdateValuesList();
287
          }
288

    
289
        }
290
      });
291
      
292
      this.cboValue.addItemListener(new ItemListener() {
293
        @Override
294
        public void itemStateChanged(ItemEvent e) {
295
          if (e.getStateChange() == ItemEvent.SELECTED) {
296
              if (cboValue.getSelectedItem()!=null && cboValue.getSelectedItem() instanceof LabeledValue ) {
297
                if (Objects.equals(((LabeledValue)cboValue.getSelectedItem()).getValue(), LOAD_MORE_ELEMENTS)) {
298
                    setUpdateValuesLimits(updateValuesTimeLimit+10, updateValuesFeaturesLimit+20000);
299
                }
300
              }
301
          }
302
        }
303
      });
304
      
305
      this.lblExtraFields.addMouseListener(new MouseAdapter() {
306
        @Override
307
        public void mouseClicked(MouseEvent e) {
308
          doSelectMoreFields();
309
        }
310
      });
311
      
312
//      clear();
313
    } catch (Exception ex) {
314
      throw new RuntimeException(ex);
315
    }
316
  }
317

    
318
  private FeatureType getFeatureType() {
319
    try {
320
      return this.store.getDefaultFeatureType();
321
    } catch (DataException ex) {
322
      return null;
323
    }
324
  }
325

    
326
  private void doSelectMoreFields() {
327
    DefaultFeatureAttributeSelectionPanel panel = new DefaultFeatureAttributeSelectionPanel(store, parameters.getFeatureType(store));
328
    WindowManager_v2 winManager = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
329
    final Dialog dialog = winManager.createDialog(
330
            panel,
331
            "Select attribute",
332
            null,
333
            WindowManager_v2.BUTTONS_OK_CANCEL
334
    );
335
    dialog.addActionListener((ActionEvent e) -> {
336
      if (dialog.getAction() == WindowManager_v2.BUTTONS_OK) {
337
        doAddAndSelect(
338
                panel.getSelectedStore(),
339
                panel.getSelectedAttributeDescriptor(),
340
                panel.getSelectedPath()
341
        );
342
      }
343
    });
344
    dialog.show(WindowManager.MODE.DIALOG);
345

    
346
  }
347

    
348
  private void doAddAndSelect(FeatureStore theStore, FeatureAttributeDescriptor attrdesc, FeatureAttributeDescriptor[] path) {
349
    ThreadSafeDialogsManager dialogManager = ToolsSwingLocator.getThreadSafeDialogsManager();
350
    I18nManager i18n = ToolsLocator.getI18nManager();
351
    DefaultComboBoxModel<Field> model = (DefaultComboBoxModel) this.ddnFields.getModel();
352
    if (attrdesc ==null) {
353
       dialogManager.messageDialog(
354
              i18n.getTranslation("_It_is_not_supported_to_search_through_this_field")+"\n"+
355
                      i18n.getTranslation("_Field_not_found"),
356
              "_Warning",
357
              JOptionPane.WARNING_MESSAGE
358
      );
359
      return;
360
    }
361

    
362
    for (int i = 0; i < model.getSize(); i++) {
363
      Field field = model.getElementAt(i);
364
      FeatureAttributeDescriptor attrdescN = field.getDescriptor();
365
      if (isTheSameStore(theStore, attrdescN.getStore())
366
              && StringUtils.equalsIgnoreCase(attrdesc.getName(), attrdescN.getName())) {
367
        this.setAttribute(i);
368
        return;
369
      }
370
    }
371
    Field field = new Field(
372
            path,
373
            theStore,
374
            attrdesc,
375
            Search.OrderedAttribute.TYPE_REGURAL,
376
            !isTheSameStore(store, theStore)
377
    );
378
    if (field.getPath().length > 2) {
379
      dialogManager.messageDialog(
380
              i18n.getTranslation("_It_is_not_supported_to_search_through_this_field") + "\n"
381
              + i18n.getTranslation("_To_many_links"),
382
              "_Warning",
383
              JOptionPane.WARNING_MESSAGE
384
      );
385
      return;
386
    }
387
    FeatureAttributeDescriptor parentDescriptor = field.getParentDescriptor();
388
    if( parentDescriptor!=null ) {
389
        switch (parentDescriptor.getRelationType()) {
390
          case DynField.RELATION_TYPE_AGGREGATE:
391
          case DynField.RELATION_TYPE_COMPOSITION:
392
            if (getForeingKeyName(field.getFeatureStore(), this.store) == null) {
393
              dialogManager.messageDialog(
394
                      "It not supported to search through this field." + "\n"
395
                      + "The link field was not found.",
396
                      "_Warning",
397
                      JOptionPane.WARNING_MESSAGE
398
              );
399
              return;
400
            }
401
            if (getPrimaryKeyName(this.store) == null) {
402
              dialogManager.messageDialog(
403
                      "It not supported to search through this field." + "\n"
404
                      + "A simple primary key was not found.",
405
                      "_Warning",
406
                      JOptionPane.WARNING_MESSAGE
407
              );
408
              return;
409
            }
410
        }
411
    }
412
    model.addElement(field);
413
    IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getCurrent();
414
    this.ddnFields.getIcons().add(iconTheme.get(attrdesc.getDataType().getIconName()));
415
    this.setAttribute(model.getSize() - 1);
416
  }
417

    
418
  public void clear() {
419
    this.ddnRelationalOperators.setSelectedIndex(0);
420
    if (this.ddnLogicalOperators != null) {
421
      this.ddnLogicalOperators.setSelectedIndex(1);
422
    }
423
    this.cboValue.setSelectedIndex(-1);
424
  }
425

    
426
  private void doUpdateValuesList() {
427
    final Field field = (Field) this.ddnFields.getSelectedItem();
428
    if (field == null) {
429
      return;
430
    }
431
    FeatureAttributeDescriptor descriptor = field.getDescriptor();
432
    if( descriptor.getType()==DataTypes.DATE ) {
433
        if( this.dateController == null ) {
434
            this.dateController = ToolsSwingLocator.getToolsSwingManager().createDatePickerController(
435
                    (JTextComponent) this.cboValue.getEditor().getEditorComponent(), 
436
                    null
437
            );
438
        }
439
    } else {
440
        if( this.dateController != null ) {
441
            this.dateController.uninstall();
442
            this.dateController = null;
443
        }
444
    }
445

    
446
    final List<Object> values = new ArrayList<>();
447
    final DefaultComboBoxModel model = new DefaultComboBoxModel();
448
    final FeatureStore theStore = field.getFeatureStore(); 
449
    final FeatureQuery query;
450
    if (this.store == theStore) {
451
        query = parameters.getQuery().getCopy(); // theStore.createFeatureQuery();
452
    } else {
453
        query = theStore.createFeatureQuery();
454
    }
455
    query.addAttributeName(field.getDescriptor().getName());
456
    query.setFilter("");
457
    query.setLimit(updateValuesFeaturesLimit);
458
    query.getGroupByColumns().clear();
459
    query.getAggregateFunctions().clear();
460
    Thread th = new Thread(new Runnable() {
461
      @Override
462
      public void run() {
463
        FeatureSet set = null;
464
        try {
465
          canHasMoreElements = false;
466
          set = theStore.getFeatureSet(query);
467
          if (set.size()>=updateValuesFeaturesLimit) {
468
            canHasMoreElements = true;
469
          }
470
          final long timeLimit = System.currentTimeMillis() + updateValuesTimeLimit * 1000;
471
          set.accept(new Visitor() {
472
            @Override
473
            public void visit(Object o) throws VisitCanceledException, BaseException {
474
              Object value = ((Feature) o).get(field.getDescriptor().getName());
475
              if (!values.contains(value)) {
476
                values.add(value);
477
              }
478
              if (System.currentTimeMillis() > timeLimit) {
479
                canHasMoreElements = true;
480
                throw new VisitCanceledException();
481
              }
482
              if (values.size() > 1000) {
483
                canHasMoreElements = true;
484
                throw new VisitCanceledException();
485
              }
486
            }
487
          });
488
        } catch (VisitCanceledException ex) {
489
          canHasMoreElements = true;
490
        } catch (Exception ex) {
491
          LOGGER.warn("Can't update list of values of '" + field.getLabel() + "'.", ex);
492
        } finally {
493
            DisposeUtils.disposeQuietly(set);
494
        }
495
        List<LabeledValue> elements = new ArrayList<>();
496
        if (!values.isEmpty()) {
497
          LabeledValue[] availableValues = field.getDescriptor().getAvailableValues();
498
          Map<String, String> availableValuesMap = new HashMap<>();
499
          if (availableValues != null) {
500
            for (LabeledValue availableValue : availableValues) {
501
              availableValuesMap.put(
502
                      Objects.toString(availableValue.getValue()),
503
                      availableValue.getLabel()
504
              );
505
            }
506
          }
507
          elements.add(new LabeledValueImpl("", null));
508
          for (Object value : values) {
509
            String key;
510
            if (value instanceof Date) {
511
                DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
512
                df.setLenient(false);
513
                key = df.format(value);
514
            } else {
515
                key = Objects.toString(value);
516
            }
517
            String label = availableValuesMap.getOrDefault(key, key);
518
            elements.add(new LabeledValueImpl(label, value));
519
          }
520
          elements.sort(null);
521

    
522
        }
523
        for (LabeledValue element : elements) {
524
          model.addElement(element);
525
        }
526
        if (canHasMoreElements) {
527
            model.addElement(new LabeledValueImpl("...", LOAD_MORE_ELEMENTS));
528
        }
529
        SwingUtilities.invokeLater(new Runnable() {
530
          @Override
531
          public void run() {
532
            setEnabled(false);
533
            cboValue.setModel(model);
534
            if (valueAssigned != null) {
535
              cboValue.setSelectedItem(valueAssigned);
536
              valueAssigned = null;
537
            }
538
            setEnabled(true);
539
          }
540
        });
541
      }
542
    });
543
    th.start();
544
  }
545

    
546
  public void setEnabled(boolean enabled) {
547
      ddnFields.setEnabled(enabled);
548
      if (ddnLogicalOperators != null) {
549
          ddnLogicalOperators.setEnabled(enabled);
550
      }
551
      ddnRelationalOperators.setEnabled(enabled);
552
      lblExtraFields.setEnabled(enabled);
553
      cboValue.setEnabled(enabled);
554
  }
555

    
556
  public String getRelationalOperator() {
557
    LabeledValue<String> op = (LabeledValue) this.ddnRelationalOperators.getSelectedItem();
558
    if (op == null) {
559
      return null;
560
    }
561
    return op.getValue();
562
  }
563

    
564
  public int setRelationalOperator(String name) {
565
    int n = 0;
566
    for (LabeledValue relationalOperator : relationalOperators) {
567
      if (StringUtils.equalsIgnoreCase(name, (CharSequence) relationalOperator.getValue())) {
568
        break;
569
      }
570
      n++;
571
    }
572
    if (this.relationalOperators.length <= n) {
573
      return -1;
574
    }
575
    this.ddnRelationalOperators.setSelectedIndex(n);
576
    return n;
577
  }
578

    
579
  public String getLogicalOperator() {
580
    if (this.ddnLogicalOperators == null) {
581
      return null;
582
    }
583
    LabeledValue<String> rel = (LabeledValue) this.ddnLogicalOperators.getSelectedItem();
584
    if (rel == null) {
585
      return null;
586
    }
587
    return rel.getValue();
588
  }
589

    
590
  public void setLogicalOperator(String operator) {
591
    if (this.ddnLogicalOperators == null) {
592
      return;
593
    }
594
    ComboBoxModel model = this.ddnLogicalOperators.getModel();
595
    for (int i = 0; i < model.getSize(); i++) {
596
      LabeledValue modelValue = (LabeledValue) model.getElementAt(i);
597
      String value = (String) modelValue.getValue();
598
      if (StringUtils.equals(value, operator)) {
599
        this.ddnLogicalOperators.setSelectedIndex(i);
600
        break;
601
      }
602
    }
603
  }
604

    
605
  public Object getValue() {
606
    final Field field = (Field) this.ddnFields.getSelectedItem();
607
    if (field == null) {
608
      return null;
609
    }
610
    Object v;
611
    if( this.dateController==null ) {
612
        v = this.cboValue.getSelectedItem();
613
    } else {
614
        v = this.dateController.get();
615
    }
616
    if (v == null) {
617
      return null;
618
    }
619
    if (v instanceof LabeledValue) {
620
      v = ((LabeledValue) v).getValue();
621
      if (v == null) {
622
        return null;
623
      }
624
    }
625
    if (v instanceof CharSequence) {
626
      if (StringUtils.isBlank((CharSequence) v)) {
627
        return null;
628
      }
629
    }
630
    Coercion coercion = field.getDescriptor().getDataType().getCoercion();
631
    try {
632
      return coercion.coerce(v);
633
    } catch (CoercionException ex) {
634
      return null;
635
    }
636
  }
637

    
638
    public void setValue(Object value) {
639
        //this.cboValue.setSelectedItem(value);
640
        SwingUtilities.invokeLater(new Runnable() {
641
            @Override
642
            public void run() {
643
        DefaultComboBoxModel model = (DefaultComboBoxModel) cboValue.getModel();
644
        for (int i = 0; i < model.getSize(); i++) {
645
            Object item = model.getElementAt(i);
646
                    if (item.equals(value)) {
647
                cboValue.setSelectedIndex(i);
648
                valueAssigned = value;
649
                return;
650
            }
651
        }
652
        // si no lo encuentra en el modelo lo a?ade
653
        final Field field = (Field) ddnFields.getSelectedItem();
654
        if (field == null) {
655
            return;
656
        } else {
657
            LabeledValue[] availableValues = field.getDescriptor().getAvailableValues();
658
            Map<String, String> availableValuesMap = new HashMap<>();
659
            if (availableValues != null) {
660
                for (LabeledValue availableValue : availableValues) {
661
                    availableValuesMap.put(
662
                            Objects.toString(availableValue.getValue()),
663
                            availableValue.getLabel()
664
                    );
665
                }
666
            }
667
            String key;
668
            if (value instanceof Date) {
669
                DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
670
                df.setLenient(false);
671
                key = df.format(value);
672
            } else {
673
                key = Objects.toString(value);
674
            }
675
            String label = availableValuesMap.getOrDefault(key, key);
676
            LabeledValueImpl newItem = new LabeledValueImpl(label, value);
677
            model.addElement(newItem);
678
            cboValue.setSelectedItem(newItem);
679
            valueAssigned = newItem;
680
        }
681
            }
682
        });
683
    }
684

    
685
  private Field getCurrentField() {
686
    final Field field = (Field) this.ddnFields.getSelectedItem();
687
    return field;
688
  }
689

    
690
  public int setAttribute(String name) {
691
    ComboBoxModel<Field> model = this.ddnFields.getModel();
692
    for (int i = 0; i < model.getSize(); i++) {
693
      Field x = model.getElementAt(i);
694
      if (StringUtils.equalsIgnoreCase(name, x.getValue())) {
695
        this.setAttribute(i);
696
        return i;
697
      }
698
    }
699
    this.setAttribute(-1);
700
    return -1;
701
  }
702

    
703
  public void setAttribute(int index) {
704
    try {
705
      this.ddnFields.setSelectedIndex(index);
706
    } catch (Exception ex) {
707
      this.ddnFields.setSelectedIndex(-1);
708
    }
709
    doUpdateValuesList();
710
  }
711

    
712
  public int setAttributePath(String[][] pathNames) {
713
    // [[attributeName, storeName],...]
714
    try {
715
      if (pathNames.length == 1) {
716
        String[] path = pathNames[pathNames.length - 1];
717
        String name = path[0];
718
        int index = this.setAttribute(name);
719
        if (index == -1) {
720
          try {
721
            FeatureAttributeDescriptor attrDescriptor = store.getDefaultFeatureType().getAttributeDescriptor(name);
722
            FeatureAttributeDescriptor[] attributePath = new FeatureAttributeDescriptor[]{attrDescriptor};
723
            if (attrDescriptor==null) {
724
                I18nManager i18n = ToolsLocator.getI18nManager();
725
                ThreadSafeDialogsManager dialogManager = ToolsSwingLocator.getThreadSafeDialogsManager();
726
                dialogManager.messageDialog(
727
                       i18n.getTranslation("_It_is_not_supported_to_search_through_this_field")+":\n "+ name+"\n"+
728
                               i18n.getTranslation("_Field_not_found_in_this_table"),
729
                       "_Warning",
730
                       JOptionPane.WARNING_MESSAGE
731
               );
732
                this.cboValue.setModel(new DefaultComboBoxModel());
733
             } else {
734
                doAddAndSelect(store, store.getDefaultFeatureType().getAttributeDescriptor(name), attributePath);
735
            }
736
          } catch (Exception ex) {
737
            LOGGER.warn("Not able to set single path into controller", ex);
738
            return -1;
739
          }
740
        }
741
        return index;
742
      } else {
743
        ComboBoxModel<Field> model = this.ddnFields.getModel();
744
        String[] singleArrayPathNameDescriptors = new String[pathNames.length];
745
        for (int i = 0; i < pathNames.length; i++) {
746
          singleArrayPathNameDescriptors[i] = pathNames[i][0];
747
        }
748
        // check the drop
749
        for (int i = 0; i < model.getSize(); i++) {
750
          Field x = model.getElementAt(i);
751
          String[] arrayDescriptors = new String[x.getPath().length];
752
          FeatureAttributeDescriptor[] path = x.getPath();
753
          for (int j = 0; j < path.length; j++) {
754
            arrayDescriptors[j] = path[j].getName();
755
          }
756
          if (Arrays.equals(singleArrayPathNameDescriptors, arrayDescriptors)) {
757
            this.setAttribute(i);
758
            return i;
759
          }
760
        }
761
        // if not, addit to the drop
762
        DataManager dataManager = DALLocator.getDataManager();
763
        String tableName = pathNames[pathNames.length - 1][1]; // del ultimo path, coger el nombre tabla
764
        FeatureStore theStore = (FeatureStore) dataManager.getStoresRepository().getStore(tableName);
765
        String attributeName = pathNames[pathNames.length - 1][0]; // del ultimo path, coger el nombre attribute
766
        if (theStore != null) {
767
          FeatureAttributeDescriptor attr;
768
          try {
769
            attr = theStore.getDefaultFeatureType().getAttributeDescriptor(attributeName);
770
            FeatureAttributeDescriptor[] attributePath = new FeatureAttributeDescriptor[2];
771
            String firstAttrName = pathNames[0][0];
772
            FeatureAttributeDescriptor firstAttr = store.getDefaultFeatureType().getAttributeDescriptor(firstAttrName);
773
            attributePath[0] = firstAttr;
774

    
775
            attributePath[1] = attr;
776
            doAddAndSelect(theStore, attr, attributePath);
777
            return SIZE_ORDERED_ATTRIBUTES - 1;
778
          } catch (Exception ex) {
779
            LOGGER.warn("Not able to set foreign path into controller", ex);
780
          }
781

    
782
        }
783

    
784
      }
785
    } catch (Exception ex) {
786
      LOGGER.warn("Controller not set.", ex);
787
    }
788
    this.setAttribute(-1);
789
    return -1;
790
  }
791

    
792
  private boolean isTheSameStore(DataStore store1, DataStore store2) {
793
    String store1FullName = store1.getFullName();
794
    String store2FullName = store2.getFullName();
795
    return StringUtils.equalsIgnoreCase(store1FullName, store2FullName);
796
  }
797

    
798
  private String getPrimaryKeyName(FeatureStore store) {
799
    try {
800
      FeatureAttributeDescriptor[] pk = store.getDefaultFeatureType().getPrimaryKey();
801
      if (pk == null || pk.length != 1) {
802
        return null;
803
      }
804
      return pk[0].getName();
805
    } catch (DataException ex) {
806
      return null;
807
    }
808
  }
809

    
810
  private String getForeingKeyName(FeatureStore store, FeatureStore foreingStore) {
811
    try {
812
      for (FeatureAttributeDescriptor descriptor : store.getDefaultFeatureType()) {
813
        if (descriptor.isForeingKey()) {
814
          ForeingKey foreingKey = descriptor.getForeingKey();
815
          if (isTheSameStore(foreingStore, foreingKey.getFeatureStore(null))) {
816
            return descriptor.getName();
817
          }
818
        }
819
      }
820
    } catch (DataException ex) {
821
      return null;
822
    }
823
    return null;
824
  }
825

    
826
  public boolean isValid(StringBuilder message) {
827
    try {
828
    Object value = this.getValue();
829
    if (value == null) {
830
      return true;
831
    }
832
    Field field = this.getCurrentField();
833
    if (field == null) {
834
      return true;
835
    }
836
    if (field.getPath().length > 2) {
837
      message.append("Invalid field '").append(field.getLabel()).append("'.\n");
838
      return false;
839
    }
840
    FeatureAttributeDescriptor descriptor = field.getDescriptor();
841
    switch (this.getRelationalOperator()) {
842
      case ExpressionBuilder.OPERATOR_EQ:
843
      case ExpressionBuilder.OPERATOR_NE:
844
      case ExpressionBuilder.OPERATOR_GT:
845
      case ExpressionBuilder.OPERATOR_GE:
846
      case ExpressionBuilder.OPERATOR_LT:
847
      case ExpressionBuilder.OPERATOR_LE:
848
        try {
849
        descriptor.getDataType().coerce(value);
850
      } catch (CoercionException ex) {
851
        message.append("Invalid value '")
852
                .append(Objects.toString(value))
853
                .append("' for field '")
854
                .append(descriptor.getLabel())
855
                .append("'.");
856
        message.append("\n");
857
        message.append(ex.getMessage());
858
        message.append("\n");
859
        return false;
860
      }
861
      break;
862

    
863
      default:
864
      case ExpressionBuilder.OPERATOR_ILIKE:
865
        break;
866
    }
867
    return true;
868
    } catch (Exception ex) {
869
        message.append("Invalid values '").append(ex.toString());
870
        return false;
871
    }
872
  }
873

    
874
  public ExpressionBuilder.Value getFilter() {
875
    ExpressionBuilder.Value filter = null;
876

    
877
    Object value = this.getValue();
878
    if (value == null) {
879
      return null;
880
    }
881
    Field field = this.getCurrentField();
882
    if (field == null) {
883
      return null;
884
    }
885
    if (field.getPath().length > 2) {
886
      // No soportado
887
      return null;
888
    }
889
    DataManager dataManager = DALLocator.getDataManager();
890
    DALExpressionBuilder builder = dataManager.createDALExpressionBuilder();
891
    FeatureAttributeDescriptor parentDescriptor = field.getParentDescriptor();
892
    FeatureAttributeDescriptor descriptor = field.getDescriptor();
893

    
894
    ExpressionBuilder.Constant value_constant = null;
895

    
896
    switch (this.getRelationalOperator()) {
897
      case ExpressionBuilder.OPERATOR_EQ:
898
      case ExpressionBuilder.OPERATOR_NE:
899
      case ExpressionBuilder.OPERATOR_GT:
900
      case ExpressionBuilder.OPERATOR_GE:
901
      case ExpressionBuilder.OPERATOR_LT:
902
      case ExpressionBuilder.OPERATOR_LE:
903
        try {
904
        value_constant = builder.expression().constant(
905
                descriptor.getDataType().coerce(value)
906
        );
907
      } catch (CoercionException ex) {
908
        return null;
909
      }
910
      break;
911

    
912
      default:
913
      case ExpressionBuilder.OPERATOR_ILIKE:
914
        value_constant = builder.expression().constant(value);
915
        break;
916
    }
917

    
918
    if (parentDescriptor == null) {
919
      // Se busca en campos de la misma tabla.
920
      filter = builder.expression().binaryOperator(
921
              this.getRelationalOperator(),
922
              builder.expression().column(this.store.getName(),descriptor.getName()),
923
              value_constant
924
      );
925
    } else {
926
      // Se busca en campos de una tabla relacionada.
927
      switch (parentDescriptor.getRelationType()) {
928
        case DynField.RELATION_TYPE_COLLABORATION:
929
        case DynField.RELATION_TYPE_IDENTITY:
930
          filter = builder.expression().binaryOperator(
931
                  this.getRelationalOperator(),
932
                  builder.foreing_value(
933
                          parentDescriptor.getName(),
934
                          descriptor.getName()
935
                  ),
936
                  value_constant
937
          );
938
          break;
939

    
940
        case DynField.RELATION_TYPE_AGGREGATE:
941
        case DynField.RELATION_TYPE_COMPOSITION:
942
          filter = builder.exists(builder.select()
943
                  .column(parentDescriptor.getFeatureType().getPrimaryKey()[0].getName())
944
                  .from(field.getFeatureStore().getName())
945
                  .limit(1)
946
                  .where(
947
                          builder.expression().and(
948
                                  builder.expression().eq(
949
                                          builder.expression().column(
950
                                                  field.getFeatureStore().getName(),
951
                                                  getForeingKeyName(field.getFeatureStore(), this.store)
952
                                          ),
953
                                          builder.expression().column(
954
                                                  this.store.getName(),
955
                                                  getPrimaryKeyName(this.store)
956
                                          )
957
                                  ),
958
                                  builder.expression().binaryOperator(
959
                                          this.getRelationalOperator(),
960
                                          builder.expression().column(
961
                                                  field.getFeatureStore().getName(),
962
                                                  descriptor.getName()
963
                                          ),
964
                                          value_constant
965
                                  )
966
                          )
967
                  )
968
                  .toValue()
969
          );
970
          break;
971
      }
972
    }
973
    return filter;
974
  }
975

    
976
  public JsonObject toJson() {
977
    JsonObjectBuilder fieldBuilder = Json.createObjectBuilder();
978

    
979
    JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
980
    for (FeatureAttributeDescriptor featureAttributeDescriptor : this.getCurrentField().getPath()) {
981
      JsonArrayBuilder pathArray = Json.createArrayBuilder();
982

    
983
      //first value: name field
984
      String fieldName = featureAttributeDescriptor.getName();
985
      pathArray.add(fieldName);
986
      //second value: name store
987
      String storeName = featureAttributeDescriptor.getFeatureType().getStore().getName();
988
      pathArray.add(storeName);
989

    
990
      arrayBuilder.add(pathArray.build());
991
    }
992
    String relational = this.getRelationalOperator();
993
    Object value = this.getValue();
994
    String strValue = DataTypeUtils.toString(value);
995
    String logical = this.getLogicalOperator();
996

    
997
    fieldBuilder.add("fieldPath", arrayBuilder.build());
998
    fieldBuilder.add("relational", relational);
999
    if (!StringUtils.isEmpty(strValue)) {
1000
      fieldBuilder.add("strValue", strValue);
1001
    }
1002
    if (!StringUtils.isEmpty(logical)) {
1003
      fieldBuilder.add("logical", logical);
1004
    }
1005
    return fieldBuilder.build();
1006
  }
1007

    
1008
  public void fromJson(JsonObject jsonState) {
1009
    if (jsonState == null) {
1010
      return;
1011
    }
1012

    
1013
    JsonArray fieldPath = jsonState.getJsonArray("fieldPath");
1014

    
1015
    // array of arrays
1016
    String[][] arrayNew = new String[fieldPath.size()][2];
1017
    for (int i = 0; i < fieldPath.size(); i++) {
1018
      String[] arrayField = new String[2];
1019
      arrayField[0] = fieldPath.getJsonArray(i).getString(0);
1020
      arrayField[1] = fieldPath.getJsonArray(i).getString(1);
1021
      arrayNew[i] = arrayField;
1022
    }
1023
    this.setAttributePath(arrayNew);  //usar el doAddAndSelect
1024

    
1025
    String relational = jsonState.getString("relational");
1026
    this.setRelationalOperator(relational);
1027

    
1028
    if (jsonState.containsKey("strValue")) {
1029
      String strValue = jsonState.getString("strValue");
1030
//        SwingUtilities.invokeLater(new Runnable() {
1031
//            @Override
1032
//            public void run() {
1033
                setValue(strValue);
1034
//            }
1035
//        });
1036
    }
1037
    if (jsonState.containsKey("logical")) {
1038
      String logical = jsonState.getString("logical");
1039
      this.setLogicalOperator(logical);
1040
    }
1041

    
1042
  }
1043
  
1044
  public void setUpdateValuesLimits(int limit, int featuresLimit) {
1045
      this.updateValuesTimeLimit = limit;
1046
      this.updateValuesFeaturesLimit = featuresLimit;
1047
      doUpdateValuesList();
1048
  }
1049
}