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

History | View | Annotate | Download (34.4 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
  }
548

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

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

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

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

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

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

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

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

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

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

    
714
            attributePath[1] = attr;
715
            doAddAndSelect(theStore, attr, attributePath);
716
            return SIZE_ORDERED_ATTRIBUTES - 1;
717
          } catch (Exception ex) {
718
            LOGGER.warn("Not able to set foreign path into controller", ex);
719
          }
720

    
721
        }
722

    
723
      }
724
    } catch (Exception ex) {
725
      LOGGER.warn("Controller not set.", ex);
726
    }
727
    this.setAttribute(-1);
728
    return -1;
729
  }
730

    
731
  private boolean isTheSameStore(DataStore store1, DataStore store2) {
732
    String store1FullName = store1.getFullName();
733
    String store2FullName = store2.getFullName();
734
    return StringUtils.equalsIgnoreCase(store1FullName, store2FullName);
735
  }
736

    
737
  private String getPrimaryKeyName(FeatureStore store) {
738
    try {
739
      FeatureAttributeDescriptor[] pk = store.getDefaultFeatureType().getPrimaryKey();
740
      if (pk == null || pk.length != 1) {
741
        return null;
742
      }
743
      return pk[0].getName();
744
    } catch (DataException ex) {
745
      return null;
746
    }
747
  }
748

    
749
  private String getForeingKeyName(FeatureStore store, FeatureStore foreingStore) {
750
    try {
751
      for (FeatureAttributeDescriptor descriptor : store.getDefaultFeatureType()) {
752
        if (descriptor.isForeingKey()) {
753
          ForeingKey foreingKey = descriptor.getForeingKey();
754
          if (isTheSameStore(foreingStore, foreingKey.getFeatureStore(null))) {
755
            return descriptor.getName();
756
          }
757
        }
758
      }
759
    } catch (DataException ex) {
760
      return null;
761
    }
762
    return null;
763
  }
764

    
765
  public boolean isValid(StringBuilder message) {
766
    try {
767
    Object value = this.getValue();
768
    if (value == null) {
769
      return true;
770
    }
771
    Field field = this.getCurrentField();
772
    if (field == null) {
773
      return true;
774
    }
775
    if (field.getPath().length > 2) {
776
      message.append("Invalid field '").append(field.getLabel()).append("'.\n");
777
      return false;
778
    }
779
    FeatureAttributeDescriptor descriptor = field.getDescriptor();
780
    switch (this.getRelationalOperator()) {
781
      case ExpressionBuilder.OPERATOR_EQ:
782
      case ExpressionBuilder.OPERATOR_NE:
783
      case ExpressionBuilder.OPERATOR_GT:
784
      case ExpressionBuilder.OPERATOR_GE:
785
      case ExpressionBuilder.OPERATOR_LT:
786
      case ExpressionBuilder.OPERATOR_LE:
787
        try {
788
        descriptor.getDataType().coerce(value);
789
      } catch (CoercionException ex) {
790
        message.append("Invalid value '")
791
                .append(Objects.toString(value))
792
                .append("' for field '")
793
                .append(descriptor.getLabel())
794
                .append("'.");
795
        message.append("\n");
796
        message.append(ex.getMessage());
797
        message.append("\n");
798
        return false;
799
      }
800
      break;
801

    
802
      default:
803
      case ExpressionBuilder.OPERATOR_ILIKE:
804
        break;
805
    }
806
    return true;
807
    } catch (Exception ex) {
808
        message.append("Invalid values '").append(ex.toString());
809
        return false;
810
    }
811
  }
812

    
813
  public ExpressionBuilder.Value getFilter() {
814
    ExpressionBuilder.Value filter = null;
815

    
816
    Object value = this.getValue();
817
    if (value == null) {
818
      return null;
819
    }
820
    Field field = this.getCurrentField();
821
    if (field == null) {
822
      return null;
823
    }
824
    if (field.getPath().length > 2) {
825
      // No soportado
826
      return null;
827
    }
828
    DataManager dataManager = DALLocator.getDataManager();
829
    DALExpressionBuilder builder = dataManager.createDALExpressionBuilder();
830
    FeatureAttributeDescriptor parentDescriptor = field.getParentDescriptor();
831
    FeatureAttributeDescriptor descriptor = field.getDescriptor();
832

    
833
    ExpressionBuilder.Constant value_constant = null;
834

    
835
    switch (this.getRelationalOperator()) {
836
      case ExpressionBuilder.OPERATOR_EQ:
837
      case ExpressionBuilder.OPERATOR_NE:
838
      case ExpressionBuilder.OPERATOR_GT:
839
      case ExpressionBuilder.OPERATOR_GE:
840
      case ExpressionBuilder.OPERATOR_LT:
841
      case ExpressionBuilder.OPERATOR_LE:
842
        try {
843
        value_constant = builder.expression().constant(
844
                descriptor.getDataType().coerce(value)
845
        );
846
      } catch (CoercionException ex) {
847
        return null;
848
      }
849
      break;
850

    
851
      default:
852
      case ExpressionBuilder.OPERATOR_ILIKE:
853
        value_constant = builder.expression().constant(value);
854
        break;
855
    }
856

    
857
    if (parentDescriptor == null) {
858
      // Se busca en campos de la misma tabla.
859
      filter = builder.expression().binaryOperator(
860
              this.getRelationalOperator(),
861
              builder.expression().column(this.store.getName(),descriptor.getName()),
862
              value_constant
863
      );
864
    } else {
865
      // Se busca en campos de una tabla relacionada.
866
      switch (parentDescriptor.getRelationType()) {
867
        case DynField.RELATION_TYPE_COLLABORATION:
868
        case DynField.RELATION_TYPE_IDENTITY:
869
          filter = builder.expression().binaryOperator(
870
                  this.getRelationalOperator(),
871
                  builder.foreing_value(
872
                          parentDescriptor.getName(),
873
                          descriptor.getName()
874
                  ),
875
                  value_constant
876
          );
877
          break;
878

    
879
        case DynField.RELATION_TYPE_AGGREGATE:
880
        case DynField.RELATION_TYPE_COMPOSITION:
881
          filter = builder.exists(builder.select()
882
                  .column(parentDescriptor.getFeatureType().getPrimaryKey()[0].getName())
883
                  .from(field.getFeatureStore().getName())
884
                  .limit(1)
885
                  .where(
886
                          builder.expression().and(
887
                                  builder.expression().eq(
888
                                          builder.expression().column(
889
                                                  field.getFeatureStore().getName(),
890
                                                  getForeingKeyName(field.getFeatureStore(), this.store)
891
                                          ),
892
                                          builder.expression().column(
893
                                                  this.store.getName(),
894
                                                  getPrimaryKeyName(this.store)
895
                                          )
896
                                  ),
897
                                  builder.expression().binaryOperator(
898
                                          this.getRelationalOperator(),
899
                                          builder.expression().column(
900
                                                  field.getFeatureStore().getName(),
901
                                                  descriptor.getName()
902
                                          ),
903
                                          value_constant
904
                                  )
905
                          )
906
                  )
907
                  .toValue()
908
          );
909
          break;
910
      }
911
    }
912
    return filter;
913
  }
914

    
915
  public JsonObject toJson() {
916
    JsonObjectBuilder fieldBuilder = Json.createObjectBuilder();
917

    
918
    JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
919
    for (FeatureAttributeDescriptor featureAttributeDescriptor : this.getCurrentField().getPath()) {
920
      JsonArrayBuilder pathArray = Json.createArrayBuilder();
921

    
922
      //first value: name field
923
      String fieldName = featureAttributeDescriptor.getName();
924
      pathArray.add(fieldName);
925
      //second value: name store
926
      String storeName = featureAttributeDescriptor.getFeatureType().getStore().getName();
927
      pathArray.add(storeName);
928

    
929
      arrayBuilder.add(pathArray.build());
930
    }
931
    String relational = this.getRelationalOperator();
932
    Object value = this.getValue();
933
    String strValue = DataTypeUtils.toString(value);
934
    String logical = this.getLogicalOperator();
935

    
936
    fieldBuilder.add("fieldPath", arrayBuilder.build());
937
    fieldBuilder.add("relational", relational);
938
    if (!StringUtils.isEmpty(strValue)) {
939
      fieldBuilder.add("strValue", strValue);
940
    }
941
    if (!StringUtils.isEmpty(logical)) {
942
      fieldBuilder.add("logical", logical);
943
    }
944
    return fieldBuilder.build();
945
  }
946

    
947
  public void fromJson(JsonObject jsonState) {
948
    if (jsonState == null) {
949
      return;
950
    }
951

    
952
    JsonArray fieldPath = jsonState.getJsonArray("fieldPath");
953

    
954
    // array of arrays
955
    String[][] arrayNew = new String[fieldPath.size()][2];
956
    for (int i = 0; i < fieldPath.size(); i++) {
957
      String[] arrayField = new String[2];
958
      arrayField[0] = fieldPath.getJsonArray(i).getString(0);
959
      arrayField[1] = fieldPath.getJsonArray(i).getString(1);
960
      arrayNew[i] = arrayField;
961
    }
962
    this.setAttributePath(arrayNew);  //usar el doAddAndSelect
963

    
964
    String relational = jsonState.getString("relational");
965
    this.setRelationalOperator(relational);
966

    
967
    if (jsonState.containsKey("strValue")) {
968
      String strValue = jsonState.getString("strValue");
969
      this.setValue(strValue);
970
    }
971
    if (jsonState.containsKey("logical")) {
972
      String logical = jsonState.getString("logical");
973
      this.setLogicalOperator(logical);
974
    }
975

    
976
  }
977
  
978
  public void setUpdateValuesLimits(int limit, int featuresLimit) {
979
      this.updateValuesTimeLimit = limit;
980
      this.updateValuesFeaturesLimit = featuresLimit;
981
      doUpdateValuesList();
982
  }
983
}