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

History | View | Annotate | Download (20.7 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 static org.gvsig.fmap.dal.swing.impl.searchpanel.DefaultSearchPanel.getAttributeDescriptorLabel;
39
import org.gvsig.tools.ToolsLocator;
40
import org.gvsig.tools.dataTypes.CoercionException;
41
import org.gvsig.tools.dataTypes.DataTypesManager;
42
import org.gvsig.tools.exception.BaseException;
43
import org.gvsig.tools.swing.api.DropDown;
44
import org.gvsig.tools.swing.api.ToolsSwingLocator;
45
import org.gvsig.tools.swing.api.ToolsSwingManager;
46
import org.gvsig.tools.swing.api.windowmanager.Dialog;
47
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
48
import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2;
49
import org.gvsig.tools.swing.icontheme.IconTheme;
50
import org.gvsig.tools.util.LabeledValue;
51
import org.gvsig.tools.util.LabeledValueImpl;
52
import org.gvsig.tools.visitor.VisitCanceledException;
53
import org.gvsig.tools.visitor.Visitor;
54
import org.slf4j.Logger;
55
import org.slf4j.LoggerFactory;
56

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

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

    
68
        FeatureAttributeDescriptor attrdesc;
69
        private final FeatureStore store;
70
        private final int type;
71
        private final boolean showStoreName;
72

    
73
        public FeatureAttribute(FeatureStore store, FeatureAttributeDescriptor attrdesc, int type) {
74
            this(store, attrdesc, null, type, false);
75
        }
76

    
77
        public FeatureAttribute(
78
                FeatureStore store,
79
                FeatureAttributeDescriptor attrdesc, 
80
                String value,
81
                int type,
82
                boolean showStoreName
83
            ) {
84
            super(
85
                    getAttributeDescriptorLabel(attrdesc, store.getName()),
86
                    ObjectUtils.defaultIfNull(value, attrdesc.getName())
87
            );
88
            this.store = store;
89
            this.attrdesc = attrdesc;
90
            this.type = type;
91
            this.showStoreName = showStoreName;
92
        }
93

    
94
        @Override
95
        public String getLabel() {
96
            String theLabel = getAttributeDescriptorLabel(attrdesc, showStoreName? store.getName():null);
97
            switch(this.type) {
98
                case Search.OrderedAttribute.TYPE_REGURAL:
99
                    break;
100
                case Search.OrderedAttribute.TYPE_FAVORITE:
101
                    theLabel = "<html><b>"+theLabel+"</b></html>";
102
                    break;
103
                case Search.OrderedAttribute.TYPE_RECENT:
104
                    theLabel = "<html><i><b>"+theLabel+"</b></i></html>";
105
                    break;
106
            }
107
            return theLabel;
108
        }
109
        
110
        public FeatureAttributeDescriptor getDescriptor() {
111
            return this.attrdesc;
112
        }
113

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

    
127
    }
128

    
129
    private FeatureStore store;
130
    private final JLabel lblFields;
131
    private final JLabel lblExtraFields;
132
    private final JLabel lblLogicalOperators;
133
    private final JLabel lblRelationalOperators;
134
    private final JComboBox cboValue;
135
    private Object valueAssigned = null;
136

    
137
    private DropDown ddnFields;
138
    private DropDown ddnLogicalOperators;
139
    private DropDown ddnRelationalOperators;
140

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

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

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

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

    
195
            DefaultComboBoxModel modelRelationalOperators = new DefaultComboBoxModel();
196
            for (LabeledValue op : relationalOperators) {
197
                modelRelationalOperators.addElement(op);
198
            }
199
            this.ddnRelationalOperators.setModel(modelRelationalOperators);
200

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

    
240
                }
241
            });
242

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

    
255
    private FeatureType getFeatureType() {
256
        try {
257
            return this.store.getDefaultFeatureType();
258
        } catch (DataException ex) {
259
            return null;
260
        }
261
    }
262

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

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

    
299
    }
300

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

    
339
    public void clear() {
340
        this.ddnRelationalOperators.setSelectedIndex(0);
341
        if (this.ddnLogicalOperators != null) {
342
            this.ddnLogicalOperators.setSelectedIndex(0);
343
        }
344
        this.cboValue.setSelectedIndex(-1);
345
    }
346

    
347
    private void doUpdateValuesList() {
348
        final FeatureAttribute attribute = (FeatureAttribute) this.ddnFields.getSelectedItem();
349
        if (attribute == null) {
350
            return;
351
        }
352

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

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

    
423
    public void setEnabled(boolean enabled) {
424
        this.ddnFields.setEnabled(enabled);
425
        if( this.ddnLogicalOperators!=null ) {
426
            this.ddnLogicalOperators.setEnabled(enabled);
427
        }
428
        this.ddnRelationalOperators.setEnabled(enabled);
429
        this.lblExtraFields.setEnabled(enabled);
430
    }
431
    
432
    public String getRelationalOperator() {
433
        LabeledValue<String> op = (LabeledValue) this.ddnRelationalOperators.getSelectedItem();
434
        if (op == null) {
435
            return null;
436
        }
437
        return op.getValue();
438
    }
439

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

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

    
507
    public String getAttribute() {
508
        final FeatureAttribute attribute = (FeatureAttribute) this.ddnFields.getSelectedItem();
509
        if (attribute == null) {
510
            return null;
511
        }
512
        if( this.getValue()!=null ) {
513
            attribute.getDescriptor().recentUsed();
514
        }
515
        return attribute.getValue();
516
    }
517

    
518
    public int setAttribute(String name) {
519
        ComboBoxModel<FeatureAttribute> model = this.ddnFields.getModel();
520
        for (int i = 0; i < model.getSize(); i++) {
521
            FeatureAttribute x = model.getElementAt(i);
522
            if (StringUtils.equalsIgnoreCase(name, x.getValue())) {
523
                this.setAttribute(i);
524
                return i;
525
            }
526
        }
527
        this.setAttribute(-1);
528
        return -1;
529
    }
530

    
531
    public void setAttribute(int index) {
532
        try {
533
            this.ddnFields.setSelectedIndex(index);
534
        } catch (Exception ex) {
535
            this.ddnFields.setSelectedIndex(-1);
536
        }
537
        doUpdateValuesList();
538
    }
539

    
540
}