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 / SearchFieldController.java @ 44297

History | View | Annotate | Download (19.3 KB)

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

    
3
import java.awt.Cursor;
4
import java.awt.Dimension;
5
import java.awt.event.ActionEvent;
6
import java.awt.event.ActionListener;
7
import java.awt.event.ItemEvent;
8
import java.awt.event.ItemListener;
9
import java.awt.event.MouseAdapter;
10
import java.awt.event.MouseEvent;
11
import java.util.ArrayList;
12
import java.util.HashMap;
13
import java.util.List;
14
import java.util.Map;
15
import java.util.Objects;
16
import javax.swing.ComboBoxModel;
17
import javax.swing.DefaultComboBoxModel;
18
import javax.swing.ImageIcon;
19
import javax.swing.JComboBox;
20
import javax.swing.JLabel;
21
import javax.swing.JScrollPane;
22
import javax.swing.JTree;
23
import javax.swing.SwingUtilities;
24
import javax.swing.tree.TreePath;
25
import org.apache.commons.lang3.ObjectUtils;
26
import org.apache.commons.lang3.StringUtils;
27
import org.gvsig.expressionevaluator.ExpressionBuilder;
28
import org.gvsig.expressionevaluator.ExpressionUtils;
29
import org.gvsig.fmap.dal.DataManager;
30
import org.gvsig.fmap.dal.complements.Search;
31
import org.gvsig.fmap.dal.exception.DataException;
32
import org.gvsig.fmap.dal.feature.Feature;
33
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
34
import org.gvsig.fmap.dal.feature.FeatureSet;
35
import org.gvsig.fmap.dal.feature.FeatureStore;
36
import org.gvsig.fmap.dal.feature.FeatureType;
37
import org.gvsig.fmap.dal.swing.impl.searchpanel.AdvancedAttributeSelectionTreeModel.Node;
38
import org.gvsig.tools.ToolsLocator;
39
import org.gvsig.tools.dataTypes.CoercionException;
40
import org.gvsig.tools.dataTypes.DataTypesManager;
41
import org.gvsig.tools.exception.BaseException;
42
import org.gvsig.tools.swing.api.DropDown;
43
import org.gvsig.tools.swing.api.ToolsSwingLocator;
44
import org.gvsig.tools.swing.api.ToolsSwingManager;
45
import org.gvsig.tools.swing.api.windowmanager.Dialog;
46
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
47
import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2;
48
import org.gvsig.tools.swing.icontheme.IconTheme;
49
import org.gvsig.tools.util.LabeledValue;
50
import org.gvsig.tools.util.LabeledValueImpl;
51
import org.gvsig.tools.visitor.VisitCanceledException;
52
import org.gvsig.tools.visitor.Visitor;
53
import org.slf4j.Logger;
54
import org.slf4j.LoggerFactory;
55

    
56
/**
57
 *
58
 * @author jjdelcerro
59
 */
60
@SuppressWarnings("UseSpecificCatch")
61
public class SearchFieldController {
62

    
63
    private static final Logger LOGGER = LoggerFactory.getLogger(SearchFieldController.class);
64
    
65
    private static class FeatureAttribute extends LabeledValueImpl<String> {
66

    
67
        FeatureAttributeDescriptor attrdesc;
68
        private final FeatureStore store;
69

    
70
        public FeatureAttribute(FeatureStore store, FeatureAttributeDescriptor attrdesc) {
71
            this(store, attrdesc, null, null);
72
        }
73

    
74
        public FeatureAttribute(
75
                FeatureStore store,
76
                FeatureAttributeDescriptor attrdesc, 
77
                String label, 
78
                String value
79
            ) {
80
            super(
81
                    ObjectUtils.defaultIfNull(label, attrdesc.getLabel()),
82
                    ObjectUtils.defaultIfNull(value, attrdesc.getName())
83
            );
84
            this.store = store;
85
            this.attrdesc = attrdesc;
86
        }
87

    
88
        public FeatureAttributeDescriptor getDescriptor() {
89
            return this.attrdesc;
90
        }
91

    
92
        public FeatureStore getFeatureStore() {
93
            return this.store;
94
        }
95
        
96
        public boolean isExpression() {
97
            FeatureType type = this.attrdesc.getFeatureType();
98
            if (type == null) {
99
                return false;
100
            }
101
            Object x = type.get(this.getValue());
102
            return x == null;
103
        }
104

    
105
    }
106

    
107
    private FeatureStore store;
108
    private final JLabel lblFields;
109
    private final JLabel lblExtraFields;
110
    private final JLabel lblLogicalOperators;
111
    private final JLabel lblRelationalOperators;
112
    private final JComboBox cboValue;
113
    private Object valueAssigned = null;
114

    
115
    private DropDown ddnFields;
116
    private DropDown ddnLogicalOperators;
117
    private DropDown ddnRelationalOperators;
118

    
119
    private final LabeledValue[] relationalOperators = {
120
        new LabeledValueImpl("Equals to", ExpressionBuilder.OPERATOR_EQ),
121
        new LabeledValueImpl("Like to", ExpressionBuilder.OPERATOR_ILIKE),
122
        new LabeledValueImpl("Not equals to", ExpressionBuilder.OPERATOR_NE),
123
        new LabeledValueImpl("Greater than", ExpressionBuilder.OPERATOR_GT),
124
        new LabeledValueImpl("Greater or equal to", ExpressionBuilder.OPERATOR_GE),
125
        new LabeledValueImpl("Less than", ExpressionBuilder.OPERATOR_LT),
126
        new LabeledValueImpl("Less or equal to", ExpressionBuilder.OPERATOR_LE)
127
    };
128
    private final LabeledValue[] logicalOperators = {
129
        new LabeledValueImpl("Or", ExpressionBuilder.OPERATOR_OR),
130
        new LabeledValueImpl("And", ExpressionBuilder.OPERATOR_AND)
131
    };
132

    
133
    public SearchFieldController(
134
            FeatureStore store,
135
            JLabel lblFields,
136
            JLabel lblExtraFields,
137
            JLabel lblRelationalOperators,
138
            JComboBox cboValue,
139
            JLabel lblLogicalOperators
140
    ) {
141
        this.store = store;
142
        this.lblFields = lblFields;
143
        this.lblExtraFields = lblExtraFields;
144
        this.lblRelationalOperators = lblRelationalOperators;
145
        this.cboValue = cboValue;
146
        this.lblLogicalOperators = lblLogicalOperators;
147
        this.initComponents();
148
    }
149

    
150
    public boolean isAValidRelationOperator(String name) {
151
        for (LabeledValue relationalOperator : relationalOperators) {
152
            if( StringUtils.equalsIgnoreCase(name, (CharSequence) relationalOperator.getValue())) {
153
                return true;
154
            }
155
        }
156
        return false;
157
    }
158
    
159
    private void initComponents() {
160
        try {
161
            ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
162
            this.lblExtraFields.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
163

    
164
            this.ddnFields = toolsSwingManager.createDropDown(lblFields);
165
            this.ddnRelationalOperators = toolsSwingManager.createDropDown(lblRelationalOperators);
166
            if (lblLogicalOperators != null) {
167
                this.ddnLogicalOperators = toolsSwingManager.createDropDown(lblLogicalOperators);
168
            }
169

    
170
            DefaultComboBoxModel modelRelationalOperators = new DefaultComboBoxModel();
171
            for (LabeledValue op : relationalOperators) {
172
                modelRelationalOperators.addElement(op);
173
            }
174
            this.ddnRelationalOperators.setModel(modelRelationalOperators);
175

    
176
            if (this.ddnLogicalOperators != null) {
177
                DefaultComboBoxModel modelLogicalOperators = new DefaultComboBoxModel();
178
                for (LabeledValue op : logicalOperators) {
179
                    modelLogicalOperators.addElement(op);
180
                }
181
                this.ddnLogicalOperators.setModel(modelLogicalOperators);
182
            }
183
            FeatureType featureType = store.getDefaultFeatureType();
184
            Search search = (Search) ToolsLocator.getComplementsManager().get(
185
                    Search.COMPLEMENT_MANE, featureType
186
            );
187
            List<FeatureAttributeDescriptor> orderedAttributes = search.getOrderedAttributes(
188
                    Search.BASIC_TYPES_FILTER,
189
                    Search.STR_INT_LONG_LABEL_ORDER,
190
                    20
191
            );
192
            List<ImageIcon>icons = new ArrayList<>();
193
            DataTypesManager dataTypeManager = ToolsLocator.getDataTypesManager();
194
            IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getCurrent();
195
            DefaultComboBoxModel model = new DefaultComboBoxModel();
196
            for (FeatureAttributeDescriptor attrdesc : orderedAttributes) {
197
                model.addElement(new FeatureAttribute(this.store, attrdesc));
198
                String iconName = attrdesc.getDataType().getIconName();
199
                if( iconTheme.exists(iconName) ) {
200
                    icons.add(iconTheme.get(iconName));
201
                } else {
202
                    icons.add(null);
203
                }
204
            }
205
            this.ddnFields.setIcons(icons);
206
            this.ddnFields.setModel(model);
207
            this.ddnFields.addItemListener(new ItemListener() {
208
                @Override
209
                public void itemStateChanged(ItemEvent e) {
210
                    if (e.getStateChange() == ItemEvent.SELECTED) {
211
                        doUpdateValuesList();
212
                    }
213

    
214
                }
215
            });
216

    
217
            this.lblExtraFields.addMouseListener(new MouseAdapter() {
218
                @Override
219
                public void mouseClicked(MouseEvent e) {
220
                    doSelectExtraField();
221
                }
222
            });
223
            clear();
224
        } catch (Exception ex) {
225
            throw new RuntimeException(ex);
226
        }
227
    }
228

    
229
    private FeatureType getFeatureType() {
230
        try {
231
            return this.store.getDefaultFeatureType();
232
        } catch (DataException ex) {
233
            return null;
234
        }
235
    }
236

    
237
    private void doSelectExtraField() {
238
        FeatureType featureType = this.getFeatureType();
239
        AdvancedAttributeSelectionTreeModel treeModel = new AdvancedAttributeSelectionTreeModel(
240
                this.store,
241
                Search.BASIC_TYPES_FILTER
242
        );
243
        final JTree tree = new JTree();
244
        tree.setCellRenderer(new AdvancedAttributeSelectionTreeCellRenderer());
245
        tree.setModel(treeModel);
246
        JScrollPane scrollpane = new JScrollPane(tree);
247
        scrollpane.setPreferredSize(new Dimension(400, 300));
248
        scrollpane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
249
        scrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
250

    
251
        WindowManager_v2 winManager = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
252
        final Dialog dialog = winManager.createDialog(
253
                scrollpane,
254
                "Select attribute",
255
                null,
256
                WindowManager_v2.BUTTONS_OK_CANCEL
257
        );
258
        dialog.addActionListener(new ActionListener() {
259
            @Override
260
            public void actionPerformed(ActionEvent e) {
261
                if (dialog.getAction() == WindowManager_v2.BUTTONS_OK) {
262
                    TreePath path = tree.getSelectionPath();
263
                    doAddAndSelect(path.getPath());
264
                }
265
            }
266
        });
267
        dialog.show(WindowManager.MODE.DIALOG);
268

    
269
    }
270

    
271
    private void doAddAndSelect(Object[] nodes) {
272
        ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
273
        ExpressionBuilder.Function list = builder.list();
274
        for (int i = 1; i < nodes.length; i++) {
275
            Node node = (Node) nodes[i];
276
            FeatureAttributeDescriptor attrdesc = node.getValue();
277
            list.parameter(builder.constant(attrdesc.getName()));
278
        }
279
        Node node = (Node) nodes[nodes.length - 1];
280
        FeatureStore theStore = node.getFeatureStore();
281
        FeatureAttributeDescriptor attrdesc = node.getValue();
282
        String storeFullName = theStore.getFullName();
283
        DefaultComboBoxModel<FeatureAttribute> model = (DefaultComboBoxModel) this.ddnFields.getModel();
284
        for (int i = 0; i < model.getSize(); i++) {
285
            FeatureAttribute attr = model.getElementAt(i);
286
            FeatureAttributeDescriptor attrdescN = attr.getDescriptor();
287
            if (StringUtils.equalsIgnoreCase(storeFullName, attrdescN.getStore().getFullName())
288
                    && StringUtils.equalsIgnoreCase(attrdesc.getName(), attrdescN.getName())) {
289
                this.setAttribute(i);
290
                return;
291
            }
292
        }
293
        String formula = builder.function(DataManager.FUNCTION_FOREING_VALUE, list).toString();
294
        String label = attrdesc.getLabel() + " [" + theStore.getName() + "]";
295
        if (StringUtils.equalsIgnoreCase(storeFullName, this.store.getFullName())) {
296
            label = attrdesc.getLabel();
297
            formula = attrdesc.getName();
298
        }
299
        FeatureAttribute attribute = new FeatureAttribute(theStore, attrdesc, label, formula);
300
        model.addElement(attribute);
301
        IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getCurrent();
302
        this.ddnFields.getIcons().add(iconTheme.get(attrdesc.getDataType().getIconName()));
303
        this.setAttribute(model.getSize() - 1);
304
    }
305

    
306
    public void clear() {
307
        this.ddnRelationalOperators.setSelectedIndex(0);
308
        if (this.ddnLogicalOperators != null) {
309
            this.ddnLogicalOperators.setSelectedIndex(0);
310
        }
311
        this.cboValue.setSelectedIndex(-1);
312
    }
313

    
314
    private void doUpdateValuesList() {
315
        final FeatureAttribute attribute = (FeatureAttribute) this.ddnFields.getSelectedItem();
316
        if (attribute == null) {
317
            return;
318
        }
319

    
320
        final List<Object> values = new ArrayList<>();
321
        final int limit = 60;
322
        final long timeLimit = System.currentTimeMillis() + limit * 1000;
323
        final DefaultComboBoxModel model = new DefaultComboBoxModel();
324
        this.setEnabled(false);
325
        Thread th = new Thread(new Runnable() {
326
            @Override
327
            public void run() {
328
                try {
329
                    FeatureSet set = attribute.getFeatureStore().getFeatureSet();
330
                    set.accept(new Visitor() {
331
                        @Override
332
                        public void visit(Object o) throws VisitCanceledException, BaseException {
333
                            Object value = ((Feature) o).get(attribute.getDescriptor().getName());
334
                            if (!values.contains(value)) {
335
                                values.add(value);
336
                            }
337
                            if (System.currentTimeMillis() > timeLimit) {
338
                                throw new VisitCanceledException();
339
                            }
340
                            if (values.size() > 1000) {
341
                                throw new VisitCanceledException();
342
                            }
343
                        }
344
                    });
345
                } catch (VisitCanceledException ex) {
346

    
347
                } catch (Exception ex) {
348
                    LOGGER.warn("Can't update list of values of '"+attribute.getLabel()+"'.", ex);
349
                }
350
                List<LabeledValue> elements = new ArrayList<>();
351
                if (!values.isEmpty()) {
352
                    LabeledValue[] availableValues = attribute.getDescriptor().getAvailableValues();
353
                    Map<String, String> availableValuesMap = new HashMap<>();
354
                    if (availableValues != null) {
355
                        for (LabeledValue availableValue : availableValues) {
356
                            availableValuesMap.put(
357
                                    Objects.toString(availableValue.getValue()),
358
                                    availableValue.getLabel()
359
                            );
360
                        }
361
                    }
362
                    elements.add(new LabeledValueImpl("", null));
363
                    for (Object value : values) {
364
                        String key = Objects.toString(value);
365
                        String label = availableValuesMap.getOrDefault(key, key);
366
                        elements.add(new LabeledValueImpl(label, value));
367
                    }
368
                    elements.sort(null);
369
                    
370
                }
371
                for (LabeledValue element : elements) {
372
                    model.addElement(element);
373
                }
374
                SwingUtilities.invokeLater(new Runnable() {
375
                    @Override
376
                    public void run() {
377
                        cboValue.setModel(model);
378
                        if( valueAssigned!=null ) {
379
                            cboValue.setSelectedItem(valueAssigned);
380
                            valueAssigned = null;
381
                        }
382
                        setEnabled(true);
383
                    }
384
                });
385
            }
386
        });
387
        th.start();
388
    }
389

    
390
    public void setEnabled(boolean enabled) {
391
        this.ddnFields.setEnabled(enabled);
392
        if( this.ddnLogicalOperators!=null ) {
393
            this.ddnLogicalOperators.setEnabled(enabled);
394
        }
395
        this.ddnRelationalOperators.setEnabled(enabled);
396
        this.lblExtraFields.setEnabled(enabled);
397
    }
398
    
399
    public String getRelationalOperator() {
400
        LabeledValue<String> op = (LabeledValue) this.ddnRelationalOperators.getSelectedItem();
401
        if (op == null) {
402
            return null;
403
        }
404
        return op.getValue();
405
    }
406

    
407
    public int setRelationalOperator(String name) {
408
        int n = 0;
409
        for (LabeledValue relationalOperator : relationalOperators) {
410
            if( StringUtils.equalsIgnoreCase(name, (CharSequence) relationalOperator.getValue())) {
411
                break;
412
            }
413
            n++;
414
        }
415
        if( this.relationalOperators.length<=n ) {
416
            return -1;
417
        }
418
        this.ddnRelationalOperators.setSelectedIndex(n);
419
        return n;
420
    }
421
    
422
    public String getLogicalOperator() {
423
        if (this.ddnLogicalOperators == null) {
424
            return null;
425
        }
426
        LabeledValue<String> rel = (LabeledValue) this.ddnLogicalOperators.getSelectedItem();
427
        if (rel == null) {
428
            return null;
429
        }
430
        return rel.getValue();
431
    }
432

    
433
    public Object getValue() {
434
        final FeatureAttribute attribute = (FeatureAttribute) this.ddnFields.getSelectedItem();
435
        if (attribute == null) {
436
            return null;
437
        }
438
        Object v = this.cboValue.getSelectedItem();
439
        if (v == null) {
440
            return null;
441
        }
442
        if (v instanceof LabeledValue) {
443
            v = ((LabeledValue) v).getValue();
444
            if (v == null) {
445
                return null;
446
            }
447
        }
448
        if (v instanceof CharSequence) {
449
            if (StringUtils.isBlank((CharSequence) v)) {
450
                return null;
451
            }
452
        }
453
        DataTypesManager.Coercion coercion = attribute.getDescriptor().getDataType().getCoercion();
454
        try {
455
            return coercion.coerce(v);
456
        } catch (CoercionException ex) {
457
            return null;
458
        }
459
    }
460
    
461
    public void setValue(Object value) {
462
        this.cboValue.setSelectedItem(value);
463
        this.valueAssigned = value;
464
    }
465
    
466
    public boolean isAttributeAnExpression() {
467
        final FeatureAttribute attribute = (FeatureAttribute) this.ddnFields.getSelectedItem();
468
        if (attribute == null) {
469
            return false;
470
        }
471
        return attribute.isExpression();
472
    }
473

    
474
    public String getAttribute() {
475
        final FeatureAttribute attribute = (FeatureAttribute) this.ddnFields.getSelectedItem();
476
        if (attribute == null) {
477
            return null;
478
        }
479
        if( this.getValue()!=null ) {
480
            attribute.getDescriptor().recentUsed();
481
        }
482
        return attribute.getValue();
483
    }
484

    
485
    public int setAttribute(String name) {
486
        ComboBoxModel<FeatureAttribute> model = this.ddnFields.getModel();
487
        for (int i = 0; i < model.getSize(); i++) {
488
            FeatureAttribute x = model.getElementAt(i);
489
            if (StringUtils.equalsIgnoreCase(name, x.getValue())) {
490
                this.setAttribute(i);
491
                return i;
492
            }
493
        }
494
        this.setAttribute(-1);
495
        return -1;
496
    }
497

    
498
    public void setAttribute(int index) {
499
        try {
500
            this.ddnFields.setSelectedIndex(index);
501
        } catch (Exception ex) {
502
            this.ddnFields.setSelectedIndex(-1);
503
        }
504
        doUpdateValuesList();
505
    }
506

    
507
};