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

History | View | Annotate | Download (30.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.util.ArrayList;
10
import java.util.Arrays;
11
import java.util.HashMap;
12
import java.util.List;
13
import java.util.Map;
14
import java.util.Objects;
15
import javax.json.Json;
16
import javax.json.JsonArray;
17
import javax.json.JsonArrayBuilder;
18
import javax.json.JsonObject;
19
import javax.json.JsonObjectBuilder;
20
import javax.swing.ComboBoxModel;
21
import javax.swing.DefaultComboBoxModel;
22
import javax.swing.ImageIcon;
23
import javax.swing.JComboBox;
24
import javax.swing.JLabel;
25
import javax.swing.JOptionPane;
26
import javax.swing.SwingUtilities;
27
import org.apache.commons.lang3.StringUtils;
28
import org.gvsig.expressionevaluator.ExpressionBuilder;
29
import org.gvsig.fmap.dal.DALLocator;
30
import org.gvsig.fmap.dal.DataManager;
31
import org.gvsig.fmap.dal.DataStore;
32
import org.gvsig.fmap.dal.complements.Search;
33
import org.gvsig.fmap.dal.exception.DataException;
34
import org.gvsig.fmap.dal.expressionevaluator.DALExpressionBuilder;
35
import org.gvsig.fmap.dal.feature.Feature;
36
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
37
import org.gvsig.fmap.dal.feature.FeatureQuery;
38
import org.gvsig.fmap.dal.feature.FeatureSet;
39
import org.gvsig.fmap.dal.feature.FeatureStore;
40
import org.gvsig.fmap.dal.feature.FeatureType;
41
import org.gvsig.fmap.dal.feature.ForeingKey;
42
import org.gvsig.fmap.dal.swing.impl.featuretype.DefaultFeatureAttributeSelectionPanel;
43
import static org.gvsig.fmap.dal.swing.impl.searchpanel.DefaultSearchPanel.getAttributeDescriptorLabel;
44
import org.gvsig.tools.ToolsLocator;
45
import org.gvsig.tools.dataTypes.Coercion;
46
import org.gvsig.tools.dataTypes.CoercionException;
47
import org.gvsig.tools.dataTypes.DataTypeUtils;
48
import org.gvsig.tools.dynobject.DynField;
49
import org.gvsig.tools.exception.BaseException;
50
import org.gvsig.tools.i18n.I18nManager;
51
import org.gvsig.tools.swing.api.DropDown;
52
import org.gvsig.tools.swing.api.ToolsSwingLocator;
53
import org.gvsig.tools.swing.api.ToolsSwingManager;
54
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
55
import org.gvsig.tools.swing.api.windowmanager.Dialog;
56
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
57
import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2;
58
import org.gvsig.tools.swing.icontheme.IconTheme;
59
import org.gvsig.tools.util.LabeledValue;
60
import org.gvsig.tools.util.LabeledValueImpl;
61
import org.gvsig.tools.visitor.VisitCanceledException;
62
import org.gvsig.tools.visitor.Visitor;
63
import org.slf4j.Logger;
64
import org.slf4j.LoggerFactory;
65

    
66
/**
67
 *
68
 * @author jjdelcerro
69
 */
70
@SuppressWarnings("UseSpecificCatch")
71
public class SearchConditionFieldController {
72

    
73
  private static final Logger LOGGER = LoggerFactory.getLogger(SearchConditionFieldController.class);
74

    
75
  private static class Field extends LabeledValueImpl<String> {
76

    
77
    FeatureAttributeDescriptor attrdesc;
78
    private final FeatureStore store;
79
    private final int presentationMode;
80
    private final boolean showStoreName;
81
    private final FeatureAttributeDescriptor[] path;
82

    
83
    public Field(FeatureAttributeDescriptor[] path, FeatureStore store, FeatureAttributeDescriptor attrdesc, int presentationMode) {
84
      this(path, store, attrdesc, presentationMode, false);
85
    }
86

    
87
    public Field(
88
            FeatureAttributeDescriptor[] path,
89
            FeatureStore store,
90
            FeatureAttributeDescriptor attrdesc,
91
            int presentationMode,
92
            boolean showStoreName
93
    ) {
94
      super(
95
              getAttributeDescriptorLabel(attrdesc, store.getName()),
96
              attrdesc.getName()
97
      );
98
      this.path = path;
99
      this.store = store;
100
      this.attrdesc = attrdesc;
101
      this.presentationMode = presentationMode;
102
      this.showStoreName = showStoreName;
103
    }
104

    
105
    public FeatureAttributeDescriptor[] getPath() {
106
      return this.path;
107
    }
108

    
109
    @Override
110
    public String getLabel() {
111
      String theLabel = getAttributeDescriptorLabel(attrdesc, showStoreName ? store.getName() : null);
112
      switch (this.presentationMode) {
113
        case Search.OrderedAttribute.TYPE_REGURAL:
114
          break;
115
        case Search.OrderedAttribute.TYPE_FAVORITE:
116
          theLabel = "<html><b>" + theLabel + "</b></html>";
117
          break;
118
        case Search.OrderedAttribute.TYPE_RECENT:
119
          theLabel = "<html><i><b>" + theLabel + "</b></i></html>";
120
          break;
121
      }
122
      return theLabel;
123
    }
124

    
125
    public FeatureAttributeDescriptor getParentDescriptor() {
126
      int l = this.path.length;
127
      if (l < 2) {
128
        return null;
129
      }
130
      return this.path[l - 2];
131
    }
132

    
133
    public FeatureAttributeDescriptor getDescriptor() {
134
      return this.attrdesc;
135
    }
136

    
137
    public FeatureStore getFeatureStore() {
138
      return this.store;
139
    }
140

    
141
  }
142

    
143
  private FeatureStore store;
144
  private final JLabel lblFields;
145
  private final JLabel lblExtraFields;
146
  private final JLabel lblLogicalOperators;
147
  private final JLabel lblRelationalOperators;
148
  private final JComboBox cboValue;
149
  private Object valueAssigned = null;
150

    
151
  private DropDown ddnFields;
152
  private DropDown ddnLogicalOperators;
153
  private DropDown ddnRelationalOperators;
154

    
155
  private LabeledValue[] relationalOperators;
156
  private LabeledValue[] logicalOperators;
157
  private final int SIZE_ORDERED_ATTRIBUTES = 20;
158

    
159
  public SearchConditionFieldController(
160
          FeatureStore store,
161
          JLabel lblFields,
162
          JLabel lblExtraFields,
163
          JLabel lblRelationalOperators,
164
          JComboBox cboValue,
165
          JLabel lblLogicalOperators
166
  ) {
167
    this.store = store;
168
    this.lblFields = lblFields;
169
    this.lblExtraFields = lblExtraFields;
170
    this.lblRelationalOperators = lblRelationalOperators;
171
    this.cboValue = cboValue;
172
    this.lblLogicalOperators = lblLogicalOperators;
173
    this.initComponents();
174
  }
175

    
176
  public boolean isAValidRelationOperator(String name) {
177
    for (LabeledValue relationalOperator : relationalOperators) {
178
      if (StringUtils.equalsIgnoreCase(name, (CharSequence) relationalOperator.getValue())) {
179
        return true;
180
      }
181
    }
182
    return false;
183
  }
184

    
185
  private void initComponents() {
186
    try {
187
      I18nManager i18n = ToolsLocator.getI18nManager();
188
      ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
189

    
190
      relationalOperators = new LabeledValue[]{
191
        new LabeledValueImpl(i18n.getTranslation("_Equals_to"), ExpressionBuilder.OPERATOR_EQ),
192
        new LabeledValueImpl(i18n.getTranslation("_Like_to"), ExpressionBuilder.OPERATOR_ILIKE),
193
        new LabeledValueImpl(i18n.getTranslation("_Not_equals_to"), ExpressionBuilder.OPERATOR_NE),
194
        new LabeledValueImpl(i18n.getTranslation("_Greater_than"), ExpressionBuilder.OPERATOR_GT),
195
        new LabeledValueImpl(i18n.getTranslation("_Greater_or_equal_to"), ExpressionBuilder.OPERATOR_GE),
196
        new LabeledValueImpl(i18n.getTranslation("_Less_than"), ExpressionBuilder.OPERATOR_LT),
197
        new LabeledValueImpl(i18n.getTranslation("_Less_or_equal_to"), ExpressionBuilder.OPERATOR_LE)
198
      };
199

    
200
      logicalOperators = new LabeledValue[]{
201
        new LabeledValueImpl(i18n.getTranslation("_Or"), ExpressionBuilder.OPERATOR_OR),
202
        new LabeledValueImpl(i18n.getTranslation("_And"), ExpressionBuilder.OPERATOR_AND)
203
      };
204

    
205
      this.lblExtraFields.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
206

    
207
      this.ddnFields = toolsSwingManager.createDropDown(lblFields);
208
      this.ddnFields.setVisibleDropdownArrow(false);
209
      this.ddnRelationalOperators = toolsSwingManager.createDropDown(lblRelationalOperators);
210
      this.ddnRelationalOperators.setVisibleDropdownArrow(false);
211
      if (lblLogicalOperators != null) {
212
        this.ddnLogicalOperators = toolsSwingManager.createDropDown(lblLogicalOperators);
213
        this.ddnLogicalOperators.setVisibleDropdownArrow(false);
214
      }
215

    
216
      DefaultComboBoxModel modelRelationalOperators = new DefaultComboBoxModel();
217
      for (LabeledValue op : relationalOperators) {
218
        modelRelationalOperators.addElement(op);
219
      }
220
      this.ddnRelationalOperators.setModel(modelRelationalOperators);
221

    
222
      if (this.ddnLogicalOperators != null) {
223
        DefaultComboBoxModel modelLogicalOperators = new DefaultComboBoxModel();
224
        for (LabeledValue op : logicalOperators) {
225
          modelLogicalOperators.addElement(op);
226
        }
227
        this.ddnLogicalOperators.setModel(modelLogicalOperators);
228
      }
229
      FeatureType featureType = store.getDefaultFeatureType();
230
      Search search = (Search) ToolsLocator.getComplementsManager().get(
231
              Search.COMPLEMENT_MANE, featureType
232
      );
233
      List<Search.OrderedAttribute> orderedAttributes = search.getOrderedAttributes(
234
              Search.BASIC_TYPES_FILTER,
235
              Search.STR_INT_LONG_LABEL_ORDER,
236
              SIZE_ORDERED_ATTRIBUTES
237
      );
238
      List<ImageIcon> icons = new ArrayList<>();
239
//            DataTypesManager dataTypeManager = ToolsLocator.getDataTypesManager();
240
      IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getCurrent();
241
      DefaultComboBoxModel model = new DefaultComboBoxModel();
242
      for (Search.OrderedAttribute attr : orderedAttributes) {
243
        FeatureAttributeDescriptor attrdesc = attr.getDescriptor();
244
        Field field = new Field(
245
                new FeatureAttributeDescriptor[]{attrdesc},
246
                this.store,
247
                attrdesc,
248
                attr.getType()
249
        );
250
        model.addElement(field);
251
        String iconName = attrdesc.getDataType().getIconName();
252
        if (iconTheme.exists(iconName)) {
253
          icons.add(iconTheme.get(iconName));
254
        } else {
255
          icons.add(null);
256
        }
257
      }
258
      this.ddnFields.setIcons(icons);
259
      this.ddnFields.setModel(model);
260
      this.ddnFields.addItemListener(new ItemListener() {
261
        @Override
262
        public void itemStateChanged(ItemEvent e) {
263
          if (e.getStateChange() == ItemEvent.SELECTED) {
264
            doUpdateValuesList();
265
          }
266

    
267
        }
268
      });
269

    
270
      this.lblExtraFields.addMouseListener(new MouseAdapter() {
271
        @Override
272
        public void mouseClicked(MouseEvent e) {
273
          doSelectMoreFields();
274
        }
275
      });
276
      clear();
277
    } catch (Exception ex) {
278
      throw new RuntimeException(ex);
279
    }
280
  }
281

    
282
  private FeatureType getFeatureType() {
283
    try {
284
      return this.store.getDefaultFeatureType();
285
    } catch (DataException ex) {
286
      return null;
287
    }
288
  }
289

    
290
  private void doSelectMoreFields() {
291
    DefaultFeatureAttributeSelectionPanel panel = new DefaultFeatureAttributeSelectionPanel(store);
292
    WindowManager_v2 winManager = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
293
    final Dialog dialog = winManager.createDialog(
294
            panel,
295
            "Select attribute",
296
            null,
297
            WindowManager_v2.BUTTONS_OK_CANCEL
298
    );
299
    dialog.addActionListener((ActionEvent e) -> {
300
      if (dialog.getAction() == WindowManager_v2.BUTTONS_OK) {
301
        doAddAndSelect(
302
                panel.getSelectedStore(),
303
                panel.getSelectedAttributeDescriptor(),
304
                panel.getSelectedPath()
305
        );
306
      }
307
    });
308
    dialog.show(WindowManager.MODE.DIALOG);
309

    
310
  }
311

    
312
  private void doAddAndSelect(FeatureStore theStore, FeatureAttributeDescriptor attrdesc, FeatureAttributeDescriptor[] path) {
313
    DefaultComboBoxModel<Field> model = (DefaultComboBoxModel) this.ddnFields.getModel();
314
    for (int i = 0; i < model.getSize(); i++) {
315
      Field field = model.getElementAt(i);
316
      FeatureAttributeDescriptor attrdescN = field.getDescriptor();
317
      if (isTheSameStore(theStore, attrdescN.getStore())
318
              && StringUtils.equalsIgnoreCase(attrdesc.getName(), attrdescN.getName())) {
319
        this.setAttribute(i);
320
        return;
321
      }
322
    }
323
    Field field = new Field(
324
            path,
325
            theStore,
326
            attrdesc,
327
            Search.OrderedAttribute.TYPE_REGURAL,
328
            !isTheSameStore(store, theStore)
329
    );
330
    ThreadSafeDialogsManager dialogManager = ToolsSwingLocator.getThreadSafeDialogsManager();
331
    if (field.getPath().length > 2) {
332
      dialogManager.messageDialog(
333
              "It not supported to search through this field." + "\n"
334
              + "Too many links.",
335
              "_Warning",
336
              JOptionPane.WARNING_MESSAGE
337
      );
338
      return;
339
    }
340
    FeatureAttributeDescriptor parentDescriptor = field.getParentDescriptor();
341
    switch (parentDescriptor.getRelationType()) {
342
      case DynField.RELATION_TYPE_AGGREGATE:
343
      case DynField.RELATION_TYPE_COMPOSITION:
344
        if (getForeingKeyName(field.getFeatureStore(), this.store) == null) {
345
          dialogManager.messageDialog(
346
                  "It not supported to search through this field." + "\n"
347
                  + "The link field was not found.",
348
                  "_Warning",
349
                  JOptionPane.WARNING_MESSAGE
350
          );
351
          return;
352
        }
353
        if (getPrimaryKeyName(this.store) == null) {
354
          dialogManager.messageDialog(
355
                  "It not supported to search through this field." + "\n"
356
                  + "A simple primary key was not found.",
357
                  "_Warning",
358
                  JOptionPane.WARNING_MESSAGE
359
          );
360
          return;
361
        }
362
    }
363
    model.addElement(field);
364
    IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getCurrent();
365
    this.ddnFields.getIcons().add(iconTheme.get(attrdesc.getDataType().getIconName()));
366
    this.setAttribute(model.getSize() - 1);
367
  }
368

    
369
  public void clear() {
370
    this.ddnRelationalOperators.setSelectedIndex(0);
371
    if (this.ddnLogicalOperators != null) {
372
      this.ddnLogicalOperators.setSelectedIndex(1);
373
    }
374
    this.cboValue.setSelectedIndex(-1);
375
  }
376

    
377
  private void doUpdateValuesList() {
378
    final Field field = (Field) this.ddnFields.getSelectedItem();
379
    if (field == null) {
380
      return;
381
    }
382

    
383
    final List<Object> values = new ArrayList<>();
384
    final int limit = 60;
385
    final long timeLimit = System.currentTimeMillis() + limit * 1000;
386
    final DefaultComboBoxModel model = new DefaultComboBoxModel();
387
    this.setEnabled(false);
388
    final FeatureStore theStore = field.getFeatureStore();
389
    final FeatureQuery query = theStore.createFeatureQuery();
390
    query.addAttributeName(field.getDescriptor().getName());
391
    query.setLimit(1000);
392
    Thread th = new Thread(new Runnable() {
393
      @Override
394
      public void run() {
395
        try {
396
          FeatureSet set = theStore.getFeatureSet(query);
397
          set.accept(new Visitor() {
398
            @Override
399
            public void visit(Object o) throws VisitCanceledException, BaseException {
400
              Object value = ((Feature) o).get(field.getDescriptor().getName());
401
              if (!values.contains(value)) {
402
                values.add(value);
403
              }
404
              if (System.currentTimeMillis() > timeLimit) {
405
                throw new VisitCanceledException();
406
              }
407
              if (values.size() > 1000) {
408
                throw new VisitCanceledException();
409
              }
410
            }
411
          });
412
        } catch (VisitCanceledException ex) {
413

    
414
        } catch (Exception ex) {
415
          LOGGER.warn("Can't update list of values of '" + field.getLabel() + "'.", ex);
416
        }
417
        List<LabeledValue> elements = new ArrayList<>();
418
        if (!values.isEmpty()) {
419
          LabeledValue[] availableValues = field.getDescriptor().getAvailableValues();
420
          Map<String, String> availableValuesMap = new HashMap<>();
421
          if (availableValues != null) {
422
            for (LabeledValue availableValue : availableValues) {
423
              availableValuesMap.put(
424
                      Objects.toString(availableValue.getValue()),
425
                      availableValue.getLabel()
426
              );
427
            }
428
          }
429
          elements.add(new LabeledValueImpl("", null));
430
          for (Object value : values) {
431
            String key = Objects.toString(value);
432
            String label = availableValuesMap.getOrDefault(key, key);
433
            elements.add(new LabeledValueImpl(label, value));
434
          }
435
          elements.sort(null);
436

    
437
        }
438
        for (LabeledValue element : elements) {
439
          model.addElement(element);
440
        }
441
        SwingUtilities.invokeLater(new Runnable() {
442
          @Override
443
          public void run() {
444
            cboValue.setModel(model);
445
            if (valueAssigned != null) {
446
              cboValue.setSelectedItem(valueAssigned);
447
              valueAssigned = null;
448
            }
449
            setEnabled(true);
450
          }
451
        });
452
      }
453
    });
454
    th.start();
455
  }
456

    
457
  public void setEnabled(boolean enabled) {
458
    this.ddnFields.setEnabled(enabled);
459
    if (this.ddnLogicalOperators != null) {
460
      this.ddnLogicalOperators.setEnabled(enabled);
461
    }
462
    this.ddnRelationalOperators.setEnabled(enabled);
463
    this.lblExtraFields.setEnabled(enabled);
464
  }
465

    
466
  public String getRelationalOperator() {
467
    LabeledValue<String> op = (LabeledValue) this.ddnRelationalOperators.getSelectedItem();
468
    if (op == null) {
469
      return null;
470
    }
471
    return op.getValue();
472
  }
473

    
474
  public int setRelationalOperator(String name) {
475
    int n = 0;
476
    for (LabeledValue relationalOperator : relationalOperators) {
477
      if (StringUtils.equalsIgnoreCase(name, (CharSequence) relationalOperator.getValue())) {
478
        break;
479
      }
480
      n++;
481
    }
482
    if (this.relationalOperators.length <= n) {
483
      return -1;
484
    }
485
    this.ddnRelationalOperators.setSelectedIndex(n);
486
    return n;
487
  }
488

    
489
  public String getLogicalOperator() {
490
    if (this.ddnLogicalOperators == null) {
491
      return null;
492
    }
493
    LabeledValue<String> rel = (LabeledValue) this.ddnLogicalOperators.getSelectedItem();
494
    if (rel == null) {
495
      return null;
496
    }
497
    return rel.getValue();
498
  }
499

    
500
  public void setLogicalOperator(String operator) {
501
    if (this.ddnLogicalOperators == null) {
502
      return;
503
    }
504
    ComboBoxModel model = this.ddnLogicalOperators.getModel();
505
    for (int i = 0; i < model.getSize(); i++) {
506
      LabeledValue modelValue = (LabeledValue) model.getElementAt(i);
507
      String value = (String) modelValue.getValue();
508
      if (StringUtils.equals(value, operator)) {
509
        this.ddnLogicalOperators.setSelectedIndex(i);
510
        break;
511
      }
512
    }
513
  }
514

    
515
  public Object getValue() {
516
    final Field field = (Field) this.ddnFields.getSelectedItem();
517
    if (field == null) {
518
      return null;
519
    }
520
    Object v = this.cboValue.getSelectedItem();
521
    if (v == null) {
522
      return null;
523
    }
524
    if (v instanceof LabeledValue) {
525
      v = ((LabeledValue) v).getValue();
526
      if (v == null) {
527
        return null;
528
      }
529
    }
530
    if (v instanceof CharSequence) {
531
      if (StringUtils.isBlank((CharSequence) v)) {
532
        return null;
533
      }
534
    }
535
    Coercion coercion = field.getDescriptor().getDataType().getCoercion();
536
    try {
537
      return coercion.coerce(v);
538
    } catch (CoercionException ex) {
539
      return null;
540
    }
541
  }
542

    
543
  public void setValue(Object value) {
544
    this.cboValue.setSelectedItem(value);
545
    this.valueAssigned = value;
546
  }
547

    
548
  private Field getCurrentField() {
549
    final Field field = (Field) this.ddnFields.getSelectedItem();
550
    return field;
551
  }
552

    
553
  public int setAttribute(String name) {
554
    ComboBoxModel<Field> model = this.ddnFields.getModel();
555
    for (int i = 0; i < model.getSize(); i++) {
556
      Field x = model.getElementAt(i);
557
      if (StringUtils.equalsIgnoreCase(name, x.getValue())) {
558
        this.setAttribute(i);
559
        return i;
560
      }
561
    }
562
    this.setAttribute(-1);
563
    return -1;
564
  }
565

    
566
  public void setAttribute(int index) {
567
    try {
568
      this.ddnFields.setSelectedIndex(index);
569
    } catch (Exception ex) {
570
      this.ddnFields.setSelectedIndex(-1);
571
    }
572
    doUpdateValuesList();
573
  }
574

    
575
  public int setAttributePath(String[][] pathNames) {
576
    // [[attributeName, storeName],...]
577
    try {
578
      if (pathNames.length == 1) {
579
        String[] path = pathNames[pathNames.length - 1];
580
        String name = path[0];
581
        int index = this.setAttribute(name);
582
        if (index == -1) {
583
          try {
584
            FeatureAttributeDescriptor attrDescriptor = store.getDefaultFeatureType().getAttributeDescriptor(name);
585
            FeatureAttributeDescriptor[] attributePath = new FeatureAttributeDescriptor[]{attrDescriptor};
586
            doAddAndSelect(store, store.getDefaultFeatureType().getAttributeDescriptor(name), attributePath);
587
          } catch (Exception ex) {
588
            LOGGER.warn("Not able to set single path into controller", ex);
589
            return -1;
590
          }
591
        }
592
        return index;
593
      } else {
594
        ComboBoxModel<Field> model = this.ddnFields.getModel();
595
        String[] singleArrayPathNameDescriptors = new String[pathNames.length];
596
        for (int i = 0; i < pathNames.length; i++) {
597
          singleArrayPathNameDescriptors[i] = pathNames[i][0];
598
        }
599
        // check the drop
600
        for (int i = 0; i < model.getSize(); i++) {
601
          Field x = model.getElementAt(i);
602
          String[] arrayDescriptors = new String[x.getPath().length];
603
          FeatureAttributeDescriptor[] path = x.getPath();
604
          for (int j = 0; j < path.length; j++) {
605
            arrayDescriptors[j] = path[j].getName();
606
          }
607
          if (Arrays.equals(singleArrayPathNameDescriptors, arrayDescriptors)) {
608
            this.setAttribute(i);
609
            return i;
610
          }
611
        }
612
        // if not, addit to the drop
613
        DataManager dataManager = DALLocator.getDataManager();
614
        String tableName = pathNames[pathNames.length - 1][1]; // del ultimo path, coger el nombre tabla
615
        FeatureStore theStore = (FeatureStore) dataManager.getStoresRepository().getStore(tableName);
616
        String attributeName = pathNames[pathNames.length - 1][0]; // del ultimo path, coger el nombre attribute
617
        if (theStore != null) {
618
          FeatureAttributeDescriptor attr;
619
          try {
620
            attr = theStore.getDefaultFeatureType().getAttributeDescriptor(attributeName);
621
            FeatureAttributeDescriptor[] attributePath = new FeatureAttributeDescriptor[2];
622
            String firstAttrName = pathNames[0][0];
623
            FeatureAttributeDescriptor firstAttr = store.getDefaultFeatureType().getAttributeDescriptor(firstAttrName);
624
            attributePath[0] = firstAttr;
625

    
626
            attributePath[1] = attr;
627
            doAddAndSelect(theStore, attr, attributePath);
628
            return SIZE_ORDERED_ATTRIBUTES - 1;
629
          } catch (Exception ex) {
630
            LOGGER.warn("Not able to set foreign path into controller", ex);
631
          }
632

    
633
        }
634

    
635
      }
636
    } catch (Exception ex) {
637
      LOGGER.warn("Controller not set.", ex);
638
    }
639
    this.setAttribute(-1);
640
    return -1;
641
  }
642

    
643
  private boolean isTheSameStore(DataStore store1, DataStore store2) {
644
    String store1FullName = store1.getFullName();
645
    String store2FullName = store2.getFullName();
646
    return StringUtils.equalsIgnoreCase(store1FullName, store2FullName);
647
  }
648

    
649
  private String getPrimaryKeyName(FeatureStore store) {
650
    try {
651
      FeatureAttributeDescriptor[] pk = store.getDefaultFeatureType().getPrimaryKey();
652
      if (pk == null || pk.length != 1) {
653
        return null;
654
      }
655
      return pk[0].getName();
656
    } catch (DataException ex) {
657
      return null;
658
    }
659
  }
660

    
661
  private String getForeingKeyName(FeatureStore store, FeatureStore foreingStore) {
662
    try {
663
      for (FeatureAttributeDescriptor descriptor : store.getDefaultFeatureType()) {
664
        if (descriptor.isForeingKey()) {
665
          ForeingKey foreingKey = descriptor.getForeingKey();
666
          if (isTheSameStore(foreingStore, foreingKey.getFeatureStore(null))) {
667
            return descriptor.getName();
668
          }
669
        }
670
      }
671
    } catch (DataException ex) {
672
      return null;
673
    }
674
    return null;
675
  }
676

    
677
  public boolean isValid(StringBuilder message) {
678
    Object value = this.getValue();
679
    if (value == null) {
680
      return true;
681
    }
682
    Field field = this.getCurrentField();
683
    if (field == null) {
684
      return true;
685
    }
686
    if (field.getPath().length > 2) {
687
      message.append("Invalid field '").append(field.getLabel()).append("'.\n");
688
      return false;
689
    }
690
    FeatureAttributeDescriptor descriptor = field.getDescriptor();
691
    switch (this.getRelationalOperator()) {
692
      case ExpressionBuilder.OPERATOR_EQ:
693
      case ExpressionBuilder.OPERATOR_NE:
694
      case ExpressionBuilder.OPERATOR_GT:
695
      case ExpressionBuilder.OPERATOR_GE:
696
      case ExpressionBuilder.OPERATOR_LT:
697
      case ExpressionBuilder.OPERATOR_LE:
698
        try {
699
        descriptor.getDataType().coerce(value);
700
      } catch (CoercionException ex) {
701
        message.append("Invalid value '")
702
                .append(Objects.toString(value))
703
                .append("' for field '")
704
                .append(descriptor.getLabel())
705
                .append("'.");
706
        message.append("\n");
707
        message.append(ex.getMessage());
708
        message.append("\n");
709
        return false;
710
      }
711
      break;
712

    
713
      default:
714
      case ExpressionBuilder.OPERATOR_ILIKE:
715
        break;
716
    }
717
    return true;
718
  }
719

    
720
  public ExpressionBuilder.Value getFilter() {
721
    ExpressionBuilder.Value filter = null;
722

    
723
    Object value = this.getValue();
724
    if (value == null) {
725
      return null;
726
    }
727
    Field field = this.getCurrentField();
728
    if (field == null) {
729
      return null;
730
    }
731
    if (field.getPath().length > 2) {
732
      // No soportado
733
      return null;
734
    }
735
    DataManager dataManager = DALLocator.getDataManager();
736
    DALExpressionBuilder builder = dataManager.createDALExpressionBuilder();
737
    FeatureAttributeDescriptor parentDescriptor = field.getParentDescriptor();
738
    FeatureAttributeDescriptor descriptor = field.getDescriptor();
739

    
740
    ExpressionBuilder.Constant value_constant = null;
741

    
742
    switch (this.getRelationalOperator()) {
743
      case ExpressionBuilder.OPERATOR_EQ:
744
      case ExpressionBuilder.OPERATOR_NE:
745
      case ExpressionBuilder.OPERATOR_GT:
746
      case ExpressionBuilder.OPERATOR_GE:
747
      case ExpressionBuilder.OPERATOR_LT:
748
      case ExpressionBuilder.OPERATOR_LE:
749
        try {
750
        value_constant = builder.expression().constant(
751
                descriptor.getDataType().coerce(value)
752
        );
753
      } catch (CoercionException ex) {
754
        return null;
755
      }
756
      break;
757

    
758
      default:
759
      case ExpressionBuilder.OPERATOR_ILIKE:
760
        value_constant = builder.expression().constant(value);
761
        break;
762
    }
763

    
764
    if (parentDescriptor == null) {
765
      // Se busca en campos de la misma tabla.
766
      filter = builder.expression().binaryOperator(
767
              this.getRelationalOperator(),
768
              builder.expression().column(this.store.getName(),descriptor.getName()),
769
              value_constant
770
      );
771
    } else {
772
      // Se busca en campos de una tabla relacionada.
773
      switch (parentDescriptor.getRelationType()) {
774
        case DynField.RELATION_TYPE_COLLABORATION:
775
        case DynField.RELATION_TYPE_IDENTITY:
776
          filter = builder.expression().binaryOperator(
777
                  this.getRelationalOperator(),
778
                  builder.foreing_value(
779
                          parentDescriptor.getName(),
780
                          descriptor.getName()
781
                  ),
782
                  value_constant
783
          );
784
          break;
785

    
786
        case DynField.RELATION_TYPE_AGGREGATE:
787
        case DynField.RELATION_TYPE_COMPOSITION:
788
          filter = builder.exists(builder.select()
789
                  .column(parentDescriptor.getFeatureType().getPrimaryKey()[0].getName())
790
                  .from(field.getFeatureStore().getName())
791
                  .limit(1)
792
                  .where(
793
                          builder.expression().and(
794
                                  builder.expression().eq(
795
                                          builder.expression().column(
796
                                                  field.getFeatureStore().getName(),
797
                                                  getForeingKeyName(field.getFeatureStore(), this.store)
798
                                          ),
799
                                          builder.expression().column(
800
                                                  this.store.getName(),
801
                                                  getPrimaryKeyName(this.store)
802
                                          )
803
                                  ),
804
                                  builder.expression().binaryOperator(
805
                                          this.getRelationalOperator(),
806
                                          builder.expression().column(this.store.getName(),descriptor.getName()),
807
                                          value_constant
808
                                  )
809
                          )
810
                  )
811
                  .toValue()
812
          );
813
          break;
814
      }
815
    }
816
    return filter;
817
  }
818

    
819
  public JsonObject toJson() {
820
    JsonObjectBuilder fieldBuilder = Json.createObjectBuilder();
821

    
822
    JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
823
    for (FeatureAttributeDescriptor featureAttributeDescriptor : this.getCurrentField().getPath()) {
824
      JsonArrayBuilder pathArray = Json.createArrayBuilder();
825

    
826
      //first value: name field
827
      String fieldName = featureAttributeDescriptor.getName();
828
      pathArray.add(fieldName);
829
      //second value: name store
830
      String storeName = featureAttributeDescriptor.getFeatureType().getStore().getName();
831
      pathArray.add(storeName);
832

    
833
      arrayBuilder.add(pathArray.build());
834
    }
835
    String relational = this.getRelationalOperator();
836
    Object value = this.getValue();
837
    String strValue = DataTypeUtils.toString(value);
838
    String logical = this.getLogicalOperator();
839

    
840
    fieldBuilder.add("fieldPath", arrayBuilder.build());
841
    fieldBuilder.add("relational", relational);
842
    if (!StringUtils.isEmpty(strValue)) {
843
      fieldBuilder.add("strValue", strValue);
844
    }
845
    if (!StringUtils.isEmpty(logical)) {
846
      fieldBuilder.add("logical", logical);
847
    }
848
    return fieldBuilder.build();
849
  }
850

    
851
  public void fromJson(JsonObject jsonState) {
852
    if (jsonState == null) {
853
      return;
854
    }
855

    
856
    JsonArray fieldPath = jsonState.getJsonArray("fieldPath");
857

    
858
    // array of arrays
859
    String[][] arrayNew = new String[fieldPath.size()][2];
860
    for (int i = 0; i < fieldPath.size(); i++) {
861
      String[] arrayField = new String[2];
862
      arrayField[0] = fieldPath.getJsonArray(i).getString(0);
863
      arrayField[1] = fieldPath.getJsonArray(i).getString(1);
864
      arrayNew[i] = arrayField;
865
    }
866
    this.setAttributePath(arrayNew);  //usar el doAddAndSelect
867

    
868
    String relational = jsonState.getString("relational");
869
    this.setRelationalOperator(relational);
870

    
871
    if (jsonState.containsKey("strValue")) {
872
      String strValue = jsonState.getString("strValue");
873
      this.setValue(strValue);
874
    }
875
    if (jsonState.containsKey("logical")) {
876
      String logical = jsonState.getString("logical");
877
      this.setLogicalOperator(logical);
878
    }
879

    
880
  }
881
}