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

History | View | Annotate | Download (35.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
      clear();
312
    } catch (Exception ex) {
313
      throw new RuntimeException(ex);
314
    }
315
  }
316

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

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

    
345
  }
346

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

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

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

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

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

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

    
540
  public void setEnabled(boolean enabled) {
541
    this.ddnFields.setEnabled(enabled);
542
    if (this.ddnLogicalOperators != null) {
543
      this.ddnLogicalOperators.setEnabled(enabled);
544
    }
545
    this.ddnRelationalOperators.setEnabled(enabled);
546
    this.lblExtraFields.setEnabled(enabled);
547
    this.cboValue.setEnabled(enabled);
548
  }
549

    
550
  public String getRelationalOperator() {
551
    LabeledValue<String> op = (LabeledValue) this.ddnRelationalOperators.getSelectedItem();
552
    if (op == null) {
553
      return null;
554
    }
555
    return op.getValue();
556
  }
557

    
558
  public int setRelationalOperator(String name) {
559
    int n = 0;
560
    for (LabeledValue relationalOperator : relationalOperators) {
561
      if (StringUtils.equalsIgnoreCase(name, (CharSequence) relationalOperator.getValue())) {
562
        break;
563
      }
564
      n++;
565
    }
566
    if (this.relationalOperators.length <= n) {
567
      return -1;
568
    }
569
    this.ddnRelationalOperators.setSelectedIndex(n);
570
    return n;
571
  }
572

    
573
  public String getLogicalOperator() {
574
    if (this.ddnLogicalOperators == null) {
575
      return null;
576
    }
577
    LabeledValue<String> rel = (LabeledValue) this.ddnLogicalOperators.getSelectedItem();
578
    if (rel == null) {
579
      return null;
580
    }
581
    return rel.getValue();
582
  }
583

    
584
  public void setLogicalOperator(String operator) {
585
    if (this.ddnLogicalOperators == null) {
586
      return;
587
    }
588
    ComboBoxModel model = this.ddnLogicalOperators.getModel();
589
    for (int i = 0; i < model.getSize(); i++) {
590
      LabeledValue modelValue = (LabeledValue) model.getElementAt(i);
591
      String value = (String) modelValue.getValue();
592
      if (StringUtils.equals(value, operator)) {
593
        this.ddnLogicalOperators.setSelectedIndex(i);
594
        break;
595
      }
596
    }
597
  }
598

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

    
632
  public void setValue(Object value) {
633
    this.cboValue.setSelectedItem(value);
634
    this.valueAssigned = value;
635
  }
636

    
637
  private Field getCurrentField() {
638
    final Field field = (Field) this.ddnFields.getSelectedItem();
639
    return field;
640
  }
641

    
642
  public int setAttribute(String name) {
643
    ComboBoxModel<Field> model = this.ddnFields.getModel();
644
    for (int i = 0; i < model.getSize(); i++) {
645
      Field x = model.getElementAt(i);
646
      if (StringUtils.equalsIgnoreCase(name, x.getValue())) {
647
        this.setAttribute(i);
648
        return i;
649
      }
650
    }
651
    this.setAttribute(-1);
652
    return -1;
653
  }
654

    
655
  public void setAttribute(int index) {
656
    try {
657
      this.ddnFields.setSelectedIndex(index);
658
    } catch (Exception ex) {
659
      this.ddnFields.setSelectedIndex(-1);
660
    }
661
    doUpdateValuesList();
662
  }
663

    
664
  public int setAttributePath(String[][] pathNames) {
665
    // [[attributeName, storeName],...]
666
    try {
667
      if (pathNames.length == 1) {
668
        String[] path = pathNames[pathNames.length - 1];
669
        String name = path[0];
670
        int index = this.setAttribute(name);
671
        if (index == -1) {
672
          try {
673
            FeatureAttributeDescriptor attrDescriptor = store.getDefaultFeatureType().getAttributeDescriptor(name);
674
            FeatureAttributeDescriptor[] attributePath = new FeatureAttributeDescriptor[]{attrDescriptor};
675
            if (attrDescriptor==null) {
676
                I18nManager i18n = ToolsLocator.getI18nManager();
677
                ThreadSafeDialogsManager dialogManager = ToolsSwingLocator.getThreadSafeDialogsManager();
678
                dialogManager.messageDialog(
679
                       i18n.getTranslation("_It_is_not_supported_to_search_through_this_field")+":\n "+ name+"\n"+
680
                               i18n.getTranslation("_Field_not_found_in_this_table"),
681
                       "_Warning",
682
                       JOptionPane.WARNING_MESSAGE
683
               );
684
                this.cboValue.setModel(new DefaultComboBoxModel());
685
             } else {
686
                doAddAndSelect(store, store.getDefaultFeatureType().getAttributeDescriptor(name), attributePath);
687
            }
688
          } catch (Exception ex) {
689
            LOGGER.warn("Not able to set single path into controller", ex);
690
            return -1;
691
          }
692
        }
693
        return index;
694
      } else {
695
        ComboBoxModel<Field> model = this.ddnFields.getModel();
696
        String[] singleArrayPathNameDescriptors = new String[pathNames.length];
697
        for (int i = 0; i < pathNames.length; i++) {
698
          singleArrayPathNameDescriptors[i] = pathNames[i][0];
699
        }
700
        // check the drop
701
        for (int i = 0; i < model.getSize(); i++) {
702
          Field x = model.getElementAt(i);
703
          String[] arrayDescriptors = new String[x.getPath().length];
704
          FeatureAttributeDescriptor[] path = x.getPath();
705
          for (int j = 0; j < path.length; j++) {
706
            arrayDescriptors[j] = path[j].getName();
707
          }
708
          if (Arrays.equals(singleArrayPathNameDescriptors, arrayDescriptors)) {
709
            this.setAttribute(i);
710
            return i;
711
          }
712
        }
713
        // if not, addit to the drop
714
        DataManager dataManager = DALLocator.getDataManager();
715
        String tableName = pathNames[pathNames.length - 1][1]; // del ultimo path, coger el nombre tabla
716
        FeatureStore theStore = (FeatureStore) dataManager.getStoresRepository().getStore(tableName);
717
        String attributeName = pathNames[pathNames.length - 1][0]; // del ultimo path, coger el nombre attribute
718
        if (theStore != null) {
719
          FeatureAttributeDescriptor attr;
720
          try {
721
            attr = theStore.getDefaultFeatureType().getAttributeDescriptor(attributeName);
722
            FeatureAttributeDescriptor[] attributePath = new FeatureAttributeDescriptor[2];
723
            String firstAttrName = pathNames[0][0];
724
            FeatureAttributeDescriptor firstAttr = store.getDefaultFeatureType().getAttributeDescriptor(firstAttrName);
725
            attributePath[0] = firstAttr;
726

    
727
            attributePath[1] = attr;
728
            doAddAndSelect(theStore, attr, attributePath);
729
            return SIZE_ORDERED_ATTRIBUTES - 1;
730
          } catch (Exception ex) {
731
            LOGGER.warn("Not able to set foreign path into controller", ex);
732
          }
733

    
734
        }
735

    
736
      }
737
    } catch (Exception ex) {
738
      LOGGER.warn("Controller not set.", ex);
739
    }
740
    this.setAttribute(-1);
741
    return -1;
742
  }
743

    
744
  private boolean isTheSameStore(DataStore store1, DataStore store2) {
745
    String store1FullName = store1.getFullName();
746
    String store2FullName = store2.getFullName();
747
    return StringUtils.equalsIgnoreCase(store1FullName, store2FullName);
748
  }
749

    
750
  private String getPrimaryKeyName(FeatureStore store) {
751
    try {
752
      FeatureAttributeDescriptor[] pk = store.getDefaultFeatureType().getPrimaryKey();
753
      if (pk == null || pk.length != 1) {
754
        return null;
755
      }
756
      return pk[0].getName();
757
    } catch (DataException ex) {
758
      return null;
759
    }
760
  }
761

    
762
  private String getForeingKeyName(FeatureStore store, FeatureStore foreingStore) {
763
    try {
764
      for (FeatureAttributeDescriptor descriptor : store.getDefaultFeatureType()) {
765
        if (descriptor.isForeingKey()) {
766
          ForeingKey foreingKey = descriptor.getForeingKey();
767
          if (isTheSameStore(foreingStore, foreingKey.getFeatureStore(null))) {
768
            return descriptor.getName();
769
          }
770
        }
771
      }
772
    } catch (DataException ex) {
773
      return null;
774
    }
775
    return null;
776
  }
777

    
778
  public boolean isValid(StringBuilder message) {
779
    try {
780
    Object value = this.getValue();
781
    if (value == null) {
782
      return true;
783
    }
784
    Field field = this.getCurrentField();
785
    if (field == null) {
786
      return true;
787
    }
788
    if (field.getPath().length > 2) {
789
      message.append("Invalid field '").append(field.getLabel()).append("'.\n");
790
      return false;
791
    }
792
    FeatureAttributeDescriptor descriptor = field.getDescriptor();
793
    switch (this.getRelationalOperator()) {
794
      case ExpressionBuilder.OPERATOR_EQ:
795
      case ExpressionBuilder.OPERATOR_NE:
796
      case ExpressionBuilder.OPERATOR_GT:
797
      case ExpressionBuilder.OPERATOR_GE:
798
      case ExpressionBuilder.OPERATOR_LT:
799
      case ExpressionBuilder.OPERATOR_LE:
800
        try {
801
        descriptor.getDataType().coerce(value);
802
      } catch (CoercionException ex) {
803
        message.append("Invalid value '")
804
                .append(Objects.toString(value))
805
                .append("' for field '")
806
                .append(descriptor.getLabel())
807
                .append("'.");
808
        message.append("\n");
809
        message.append(ex.getMessage());
810
        message.append("\n");
811
        return false;
812
      }
813
      break;
814

    
815
      default:
816
      case ExpressionBuilder.OPERATOR_ILIKE:
817
        break;
818
    }
819
    return true;
820
    } catch (Exception ex) {
821
        message.append("Invalid values '").append(ex.toString());
822
        return false;
823
    }
824
  }
825

    
826
  public ExpressionBuilder.Value getFilter() {
827
    ExpressionBuilder.Value filter = null;
828

    
829
    Object value = this.getValue();
830
    if (value == null) {
831
      return null;
832
    }
833
    Field field = this.getCurrentField();
834
    if (field == null) {
835
      return null;
836
    }
837
    if (field.getPath().length > 2) {
838
      // No soportado
839
      return null;
840
    }
841
    DataManager dataManager = DALLocator.getDataManager();
842
    DALExpressionBuilder builder = dataManager.createDALExpressionBuilder();
843
    FeatureAttributeDescriptor parentDescriptor = field.getParentDescriptor();
844
    FeatureAttributeDescriptor descriptor = field.getDescriptor();
845

    
846
    ExpressionBuilder.Constant value_constant = null;
847

    
848
    switch (this.getRelationalOperator()) {
849
      case ExpressionBuilder.OPERATOR_EQ:
850
      case ExpressionBuilder.OPERATOR_NE:
851
      case ExpressionBuilder.OPERATOR_GT:
852
      case ExpressionBuilder.OPERATOR_GE:
853
      case ExpressionBuilder.OPERATOR_LT:
854
      case ExpressionBuilder.OPERATOR_LE:
855
        try {
856
        value_constant = builder.expression().constant(
857
                descriptor.getDataType().coerce(value)
858
        );
859
      } catch (CoercionException ex) {
860
        return null;
861
      }
862
      break;
863

    
864
      default:
865
      case ExpressionBuilder.OPERATOR_ILIKE:
866
        value_constant = builder.expression().constant(value);
867
        break;
868
    }
869

    
870
    if (parentDescriptor == null) {
871
      // Se busca en campos de la misma tabla.
872
      filter = builder.expression().binaryOperator(
873
              this.getRelationalOperator(),
874
              builder.expression().column(this.store.getName(),descriptor.getName()),
875
              value_constant
876
      );
877
    } else {
878
      // Se busca en campos de una tabla relacionada.
879
      switch (parentDescriptor.getRelationType()) {
880
        case DynField.RELATION_TYPE_COLLABORATION:
881
        case DynField.RELATION_TYPE_IDENTITY:
882
          filter = builder.expression().binaryOperator(
883
                  this.getRelationalOperator(),
884
                  builder.foreing_value(
885
                          parentDescriptor.getName(),
886
                          descriptor.getName()
887
                  ),
888
                  value_constant
889
          );
890
          break;
891

    
892
        case DynField.RELATION_TYPE_AGGREGATE:
893
        case DynField.RELATION_TYPE_COMPOSITION:
894
          filter = builder.exists(builder.select()
895
                  .column(parentDescriptor.getFeatureType().getPrimaryKey()[0].getName())
896
                  .from(field.getFeatureStore().getName())
897
                  .limit(1)
898
                  .where(
899
                          builder.expression().and(
900
                                  builder.expression().eq(
901
                                          builder.expression().column(
902
                                                  field.getFeatureStore().getName(),
903
                                                  getForeingKeyName(field.getFeatureStore(), this.store)
904
                                          ),
905
                                          builder.expression().column(
906
                                                  this.store.getName(),
907
                                                  getPrimaryKeyName(this.store)
908
                                          )
909
                                  ),
910
                                  builder.expression().binaryOperator(
911
                                          this.getRelationalOperator(),
912
                                          builder.expression().column(
913
                                                  field.getFeatureStore().getName(),
914
                                                  descriptor.getName()
915
                                          ),
916
                                          value_constant
917
                                  )
918
                          )
919
                  )
920
                  .toValue()
921
          );
922
          break;
923
      }
924
    }
925
    return filter;
926
  }
927

    
928
  public JsonObject toJson() {
929
    JsonObjectBuilder fieldBuilder = Json.createObjectBuilder();
930

    
931
    JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
932
    for (FeatureAttributeDescriptor featureAttributeDescriptor : this.getCurrentField().getPath()) {
933
      JsonArrayBuilder pathArray = Json.createArrayBuilder();
934

    
935
      //first value: name field
936
      String fieldName = featureAttributeDescriptor.getName();
937
      pathArray.add(fieldName);
938
      //second value: name store
939
      String storeName = featureAttributeDescriptor.getFeatureType().getStore().getName();
940
      pathArray.add(storeName);
941

    
942
      arrayBuilder.add(pathArray.build());
943
    }
944
    String relational = this.getRelationalOperator();
945
    Object value = this.getValue();
946
    String strValue = DataTypeUtils.toString(value);
947
    String logical = this.getLogicalOperator();
948

    
949
    fieldBuilder.add("fieldPath", arrayBuilder.build());
950
    fieldBuilder.add("relational", relational);
951
    if (!StringUtils.isEmpty(strValue)) {
952
      fieldBuilder.add("strValue", strValue);
953
    }
954
    if (!StringUtils.isEmpty(logical)) {
955
      fieldBuilder.add("logical", logical);
956
    }
957
    return fieldBuilder.build();
958
  }
959

    
960
  public void fromJson(JsonObject jsonState) {
961
    if (jsonState == null) {
962
      return;
963
    }
964

    
965
    JsonArray fieldPath = jsonState.getJsonArray("fieldPath");
966

    
967
    // array of arrays
968
    String[][] arrayNew = new String[fieldPath.size()][2];
969
    for (int i = 0; i < fieldPath.size(); i++) {
970
      String[] arrayField = new String[2];
971
      arrayField[0] = fieldPath.getJsonArray(i).getString(0);
972
      arrayField[1] = fieldPath.getJsonArray(i).getString(1);
973
      arrayNew[i] = arrayField;
974
    }
975
    this.setAttributePath(arrayNew);  //usar el doAddAndSelect
976

    
977
    String relational = jsonState.getString("relational");
978
    this.setRelationalOperator(relational);
979

    
980
    if (jsonState.containsKey("strValue")) {
981
      String strValue = jsonState.getString("strValue");
982
      this.setValue(strValue);
983
    }
984
    if (jsonState.containsKey("logical")) {
985
      String logical = jsonState.getString("logical");
986
      this.setLogicalOperator(logical);
987
    }
988

    
989
  }
990
  
991
  public void setUpdateValuesLimits(int limit, int featuresLimit) {
992
      this.updateValuesTimeLimit = limit;
993
      this.updateValuesFeaturesLimit = featuresLimit;
994
      doUpdateValuesList();
995
  }
996
}