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

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

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

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

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

    
348
  }
349

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
784
        }
785

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

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

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

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

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

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

    
876
  public ExpressionBuilder.Value getFilter() {
877
    ExpressionBuilder.Value filter = null;
878

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

    
896
    ExpressionBuilder.Constant value_constant = null;
897

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

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

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

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

    
978
  public JsonObject toJson() {
979
    JsonObjectBuilder fieldBuilder = Json.createObjectBuilder();
980

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

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

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

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

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

    
1015
    JsonArray fieldPath = jsonState.getJsonArray("fieldPath");
1016

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

    
1027
    String relational = jsonState.getString("relational");
1028
    this.setRelationalOperator(relational);
1029

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

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