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

History | View | Annotate | Download (20.4 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
        private final int type;
70

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

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

    
91
        @Override
92
        public String getLabel() {
93
            String theLabel = super.getLabel();
94
            switch(this.type) {
95
                case Search.OrderedAttribute.TYPE_REGURAL:
96
                    break;
97
                case Search.OrderedAttribute.TYPE_FAVORITE:
98
                    theLabel = "<html><b>"+theLabel+"</b></html>";
99
                    break;
100
                case Search.OrderedAttribute.TYPE_RECENT:
101
                    theLabel = "<html><i><b>"+theLabel+"</b></i></html>";
102
                    break;
103
            }
104
            return theLabel;
105
        }
106
        
107
        public FeatureAttributeDescriptor getDescriptor() {
108
            return this.attrdesc;
109
        }
110

    
111
        public FeatureStore getFeatureStore() {
112
            return this.store;
113
        }
114
        
115
        public boolean isExpression() {
116
            FeatureType type = this.attrdesc.getFeatureType();
117
            if (type == null) {
118
                return false;
119
            }
120
            Object x = type.get(this.getValue());
121
            return x == null;
122
        }
123

    
124
    }
125

    
126
    private FeatureStore store;
127
    private final JLabel lblFields;
128
    private final JLabel lblExtraFields;
129
    private final JLabel lblLogicalOperators;
130
    private final JLabel lblRelationalOperators;
131
    private final JComboBox cboValue;
132
    private Object valueAssigned = null;
133

    
134
    private DropDown ddnFields;
135
    private DropDown ddnLogicalOperators;
136
    private DropDown ddnRelationalOperators;
137

    
138
    private final LabeledValue[] relationalOperators = {
139
        new LabeledValueImpl("Equals to", ExpressionBuilder.OPERATOR_EQ),
140
        new LabeledValueImpl("Like to", ExpressionBuilder.OPERATOR_ILIKE),
141
        new LabeledValueImpl("Not equals to", ExpressionBuilder.OPERATOR_NE),
142
        new LabeledValueImpl("Greater than", ExpressionBuilder.OPERATOR_GT),
143
        new LabeledValueImpl("Greater or equal to", ExpressionBuilder.OPERATOR_GE),
144
        new LabeledValueImpl("Less than", ExpressionBuilder.OPERATOR_LT),
145
        new LabeledValueImpl("Less or equal to", ExpressionBuilder.OPERATOR_LE)
146
    };
147
    private final LabeledValue[] logicalOperators = {
148
        new LabeledValueImpl("Or", ExpressionBuilder.OPERATOR_OR),
149
        new LabeledValueImpl("And", ExpressionBuilder.OPERATOR_AND)
150
    };
151

    
152
    public SearchFieldController(
153
            FeatureStore store,
154
            JLabel lblFields,
155
            JLabel lblExtraFields,
156
            JLabel lblRelationalOperators,
157
            JComboBox cboValue,
158
            JLabel lblLogicalOperators
159
    ) {
160
        this.store = store;
161
        this.lblFields = lblFields;
162
        this.lblExtraFields = lblExtraFields;
163
        this.lblRelationalOperators = lblRelationalOperators;
164
        this.cboValue = cboValue;
165
        this.lblLogicalOperators = lblLogicalOperators;
166
        this.initComponents();
167
    }
168

    
169
    public boolean isAValidRelationOperator(String name) {
170
        for (LabeledValue relationalOperator : relationalOperators) {
171
            if( StringUtils.equalsIgnoreCase(name, (CharSequence) relationalOperator.getValue())) {
172
                return true;
173
            }
174
        }
175
        return false;
176
    }
177
    
178
    private void initComponents() {
179
        try {
180
            ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
181
            this.lblExtraFields.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
182

    
183
            this.ddnFields = toolsSwingManager.createDropDown(lblFields);
184
            this.ddnFields.setVisibleDropdownArrow(false);
185
            this.ddnRelationalOperators = toolsSwingManager.createDropDown(lblRelationalOperators);
186
            this.ddnRelationalOperators.setVisibleDropdownArrow(false);
187
            if (lblLogicalOperators != null) {
188
                this.ddnLogicalOperators = toolsSwingManager.createDropDown(lblLogicalOperators);
189
                this.ddnLogicalOperators.setVisibleDropdownArrow(false);
190
            }
191

    
192
            DefaultComboBoxModel modelRelationalOperators = new DefaultComboBoxModel();
193
            for (LabeledValue op : relationalOperators) {
194
                modelRelationalOperators.addElement(op);
195
            }
196
            this.ddnRelationalOperators.setModel(modelRelationalOperators);
197

    
198
            if (this.ddnLogicalOperators != null) {
199
                DefaultComboBoxModel modelLogicalOperators = new DefaultComboBoxModel();
200
                for (LabeledValue op : logicalOperators) {
201
                    modelLogicalOperators.addElement(op);
202
                }
203
                this.ddnLogicalOperators.setModel(modelLogicalOperators);
204
            }
205
            FeatureType featureType = store.getDefaultFeatureType();
206
            Search search = (Search) ToolsLocator.getComplementsManager().get(
207
                    Search.COMPLEMENT_MANE, featureType
208
            );
209
            List<Search.OrderedAttribute> orderedAttributes = search.getOrderedAttributes(
210
                    Search.BASIC_TYPES_FILTER,
211
                    Search.STR_INT_LONG_LABEL_ORDER,
212
                    20
213
            );
214
            List<ImageIcon>icons = new ArrayList<>();
215
//            DataTypesManager dataTypeManager = ToolsLocator.getDataTypesManager();
216
            IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getCurrent();
217
            DefaultComboBoxModel model = new DefaultComboBoxModel();
218
            for (Search.OrderedAttribute attr : orderedAttributes) {
219
                FeatureAttributeDescriptor attrdesc = attr.getDescriptor();
220
                model.addElement(new FeatureAttribute(this.store, attrdesc, attr.getType()));
221
                String iconName = attrdesc.getDataType().getIconName();
222
                if( iconTheme.exists(iconName) ) {
223
                    icons.add(iconTheme.get(iconName));
224
                } else {
225
                    icons.add(null);
226
                }
227
            }
228
            this.ddnFields.setIcons(icons);
229
            this.ddnFields.setModel(model);
230
            this.ddnFields.addItemListener(new ItemListener() {
231
                @Override
232
                public void itemStateChanged(ItemEvent e) {
233
                    if (e.getStateChange() == ItemEvent.SELECTED) {
234
                        doUpdateValuesList();
235
                    }
236

    
237
                }
238
            });
239

    
240
            this.lblExtraFields.addMouseListener(new MouseAdapter() {
241
                @Override
242
                public void mouseClicked(MouseEvent e) {
243
                    doSelectExtraField();
244
                }
245
            });
246
            clear();
247
        } catch (Exception ex) {
248
            throw new RuntimeException(ex);
249
        }
250
    }
251

    
252
    private FeatureType getFeatureType() {
253
        try {
254
            return this.store.getDefaultFeatureType();
255
        } catch (DataException ex) {
256
            return null;
257
        }
258
    }
259

    
260
    private void doSelectExtraField() {
261
        FeatureType featureType = this.getFeatureType();
262
        AdvancedAttributeSelectionTreeModel treeModel = new AdvancedAttributeSelectionTreeModel(
263
                this.store,
264
                Search.BASIC_TYPES_FILTER
265
        );
266
        final JTree tree = new JTree();
267
        tree.setCellRenderer(new AdvancedAttributeSelectionTreeCellRenderer());
268
        tree.setModel(treeModel);
269
        try {
270
            tree.setSelectionRow(1);
271
        } catch(Throwable th) {
272
        }
273
        JScrollPane scrollpane = new JScrollPane(tree);
274
        scrollpane.setPreferredSize(new Dimension(400, 300));
275
        scrollpane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
276
        scrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
277

    
278
        WindowManager_v2 winManager = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
279
        final Dialog dialog = winManager.createDialog(
280
                scrollpane,
281
                "Select attribute",
282
                null,
283
                WindowManager_v2.BUTTONS_OK_CANCEL
284
        );
285
        dialog.addActionListener(new ActionListener() {
286
            @Override
287
            public void actionPerformed(ActionEvent e) {
288
                if (dialog.getAction() == WindowManager_v2.BUTTONS_OK) {
289
                    TreePath path = tree.getSelectionPath();
290
                    doAddAndSelect(path.getPath());
291
                }
292
            }
293
        });
294
        dialog.show(WindowManager.MODE.DIALOG);
295

    
296
    }
297

    
298
    private void doAddAndSelect(Object[] nodes) {
299
        ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
300
        ExpressionBuilder.Function list = builder.list();
301
        for (int i = 1; i < nodes.length; i++) {
302
            Node node = (Node) nodes[i];
303
            FeatureAttributeDescriptor attrdesc = node.getValue();
304
            list.parameter(builder.constant(attrdesc.getName()));
305
        }
306
        Node node = (Node) nodes[nodes.length - 1];
307
        FeatureStore theStore = node.getFeatureStore();
308
        FeatureAttributeDescriptor attrdesc = node.getValue();
309
        String storeFullName = theStore.getFullName();
310
        DefaultComboBoxModel<FeatureAttribute> model = (DefaultComboBoxModel) this.ddnFields.getModel();
311
        for (int i = 0; i < model.getSize(); i++) {
312
            FeatureAttribute attr = model.getElementAt(i);
313
            FeatureAttributeDescriptor attrdescN = attr.getDescriptor();
314
            if (StringUtils.equalsIgnoreCase(storeFullName, attrdescN.getStore().getFullName())
315
                    && StringUtils.equalsIgnoreCase(attrdesc.getName(), attrdescN.getName())) {
316
                this.setAttribute(i);
317
                return;
318
            }
319
        }
320
        String formula = builder.function(DataManager.FUNCTION_FOREING_VALUE, list).toString();
321
        String label = attrdesc.getLabel() + " [" + theStore.getName() + "]";
322
        if (StringUtils.equalsIgnoreCase(storeFullName, this.store.getFullName())) {
323
            label = attrdesc.getLocalizedLabel();
324
            formula = attrdesc.getName();
325
        }
326
        FeatureAttribute attribute = new FeatureAttribute(theStore, attrdesc, label, formula, Search.OrderedAttribute.TYPE_REGURAL);
327
        model.addElement(attribute);
328
        IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getCurrent();
329
        this.ddnFields.getIcons().add(iconTheme.get(attrdesc.getDataType().getIconName()));
330
        this.setAttribute(model.getSize() - 1);
331
    }
332

    
333
    public void clear() {
334
        this.ddnRelationalOperators.setSelectedIndex(0);
335
        if (this.ddnLogicalOperators != null) {
336
            this.ddnLogicalOperators.setSelectedIndex(0);
337
        }
338
        this.cboValue.setSelectedIndex(-1);
339
    }
340

    
341
    private void doUpdateValuesList() {
342
        final FeatureAttribute attribute = (FeatureAttribute) this.ddnFields.getSelectedItem();
343
        if (attribute == null) {
344
            return;
345
        }
346

    
347
        final List<Object> values = new ArrayList<>();
348
        final int limit = 60;
349
        final long timeLimit = System.currentTimeMillis() + limit * 1000;
350
        final DefaultComboBoxModel model = new DefaultComboBoxModel();
351
        this.setEnabled(false);
352
        Thread th = new Thread(new Runnable() {
353
            @Override
354
            public void run() {
355
                try {
356
                    FeatureSet set = attribute.getFeatureStore().getFeatureSet();
357
                    set.accept(new Visitor() {
358
                        @Override
359
                        public void visit(Object o) throws VisitCanceledException, BaseException {
360
                            Object value = ((Feature) o).get(attribute.getDescriptor().getName());
361
                            if (!values.contains(value)) {
362
                                values.add(value);
363
                            }
364
                            if (System.currentTimeMillis() > timeLimit) {
365
                                throw new VisitCanceledException();
366
                            }
367
                            if (values.size() > 1000) {
368
                                throw new VisitCanceledException();
369
                            }
370
                        }
371
                    });
372
                } catch (VisitCanceledException ex) {
373

    
374
                } catch (Exception ex) {
375
                    LOGGER.warn("Can't update list of values of '"+attribute.getLabel()+"'.", ex);
376
                }
377
                List<LabeledValue> elements = new ArrayList<>();
378
                if (!values.isEmpty()) {
379
                    LabeledValue[] availableValues = attribute.getDescriptor().getAvailableValues();
380
                    Map<String, String> availableValuesMap = new HashMap<>();
381
                    if (availableValues != null) {
382
                        for (LabeledValue availableValue : availableValues) {
383
                            availableValuesMap.put(
384
                                    Objects.toString(availableValue.getValue()),
385
                                    availableValue.getLabel()
386
                            );
387
                        }
388
                    }
389
                    elements.add(new LabeledValueImpl("", null));
390
                    for (Object value : values) {
391
                        String key = Objects.toString(value);
392
                        String label = availableValuesMap.getOrDefault(key, key);
393
                        elements.add(new LabeledValueImpl(label, value));
394
                    }
395
                    elements.sort(null);
396
                    
397
                }
398
                for (LabeledValue element : elements) {
399
                    model.addElement(element);
400
                }
401
                SwingUtilities.invokeLater(new Runnable() {
402
                    @Override
403
                    public void run() {
404
                        cboValue.setModel(model);
405
                        if( valueAssigned!=null ) {
406
                            cboValue.setSelectedItem(valueAssigned);
407
                            valueAssigned = null;
408
                        }
409
                        setEnabled(true);
410
                    }
411
                });
412
            }
413
        });
414
        th.start();
415
    }
416

    
417
    public void setEnabled(boolean enabled) {
418
        this.ddnFields.setEnabled(enabled);
419
        if( this.ddnLogicalOperators!=null ) {
420
            this.ddnLogicalOperators.setEnabled(enabled);
421
        }
422
        this.ddnRelationalOperators.setEnabled(enabled);
423
        this.lblExtraFields.setEnabled(enabled);
424
    }
425
    
426
    public String getRelationalOperator() {
427
        LabeledValue<String> op = (LabeledValue) this.ddnRelationalOperators.getSelectedItem();
428
        if (op == null) {
429
            return null;
430
        }
431
        return op.getValue();
432
    }
433

    
434
    public int setRelationalOperator(String name) {
435
        int n = 0;
436
        for (LabeledValue relationalOperator : relationalOperators) {
437
            if( StringUtils.equalsIgnoreCase(name, (CharSequence) relationalOperator.getValue())) {
438
                break;
439
            }
440
            n++;
441
        }
442
        if( this.relationalOperators.length<=n ) {
443
            return -1;
444
        }
445
        this.ddnRelationalOperators.setSelectedIndex(n);
446
        return n;
447
    }
448
    
449
    public String getLogicalOperator() {
450
        if (this.ddnLogicalOperators == null) {
451
            return null;
452
        }
453
        LabeledValue<String> rel = (LabeledValue) this.ddnLogicalOperators.getSelectedItem();
454
        if (rel == null) {
455
            return null;
456
        }
457
        return rel.getValue();
458
    }
459

    
460
    public Object getValue() {
461
        final FeatureAttribute attribute = (FeatureAttribute) this.ddnFields.getSelectedItem();
462
        if (attribute == null) {
463
            return null;
464
        }
465
        Object v = this.cboValue.getSelectedItem();
466
        if (v == null) {
467
            return null;
468
        }
469
        if (v instanceof LabeledValue) {
470
            v = ((LabeledValue) v).getValue();
471
            if (v == null) {
472
                return null;
473
            }
474
        }
475
        if (v instanceof CharSequence) {
476
            if (StringUtils.isBlank((CharSequence) v)) {
477
                return null;
478
            }
479
        }
480
        DataTypesManager.Coercion coercion = attribute.getDescriptor().getDataType().getCoercion();
481
        try {
482
            return coercion.coerce(v);
483
        } catch (CoercionException ex) {
484
            return null;
485
        }
486
    }
487
    
488
    public void setValue(Object value) {
489
        this.cboValue.setSelectedItem(value);
490
        this.valueAssigned = value;
491
    }
492
    
493
    public boolean isAttributeAnExpression() {
494
        final FeatureAttribute attribute = (FeatureAttribute) this.ddnFields.getSelectedItem();
495
        if (attribute == null) {
496
            return false;
497
        }
498
        return attribute.isExpression();
499
    }
500

    
501
    public String getAttribute() {
502
        final FeatureAttribute attribute = (FeatureAttribute) this.ddnFields.getSelectedItem();
503
        if (attribute == null) {
504
            return null;
505
        }
506
        if( this.getValue()!=null ) {
507
            attribute.getDescriptor().recentUsed();
508
        }
509
        return attribute.getValue();
510
    }
511

    
512
    public int setAttribute(String name) {
513
        ComboBoxModel<FeatureAttribute> model = this.ddnFields.getModel();
514
        for (int i = 0; i < model.getSize(); i++) {
515
            FeatureAttribute x = model.getElementAt(i);
516
            if (StringUtils.equalsIgnoreCase(name, x.getValue())) {
517
                this.setAttribute(i);
518
                return i;
519
            }
520
        }
521
        this.setAttribute(-1);
522
        return -1;
523
    }
524

    
525
    public void setAttribute(int index) {
526
        try {
527
            this.ddnFields.setSelectedIndex(index);
528
        } catch (Exception ex) {
529
            this.ddnFields.setSelectedIndex(-1);
530
        }
531
        doUpdateValuesList();
532
    }
533

    
534
};