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

History | View | Annotate | Download (17.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.JComboBox;
19
import javax.swing.JLabel;
20
import javax.swing.JScrollPane;
21
import javax.swing.JTree;
22
import javax.swing.SwingUtilities;
23
import javax.swing.tree.TreePath;
24
import org.apache.commons.lang3.ObjectUtils;
25
import org.apache.commons.lang3.StringUtils;
26
import org.gvsig.expressionevaluator.ExpressionBuilder;
27
import org.gvsig.expressionevaluator.ExpressionUtils;
28
import org.gvsig.fmap.dal.DataManager;
29
import org.gvsig.fmap.dal.complements.Search;
30
import org.gvsig.fmap.dal.exception.DataException;
31
import org.gvsig.fmap.dal.feature.Feature;
32
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
33
import org.gvsig.fmap.dal.feature.FeatureSet;
34
import org.gvsig.fmap.dal.feature.FeatureStore;
35
import org.gvsig.fmap.dal.feature.FeatureType;
36
import org.gvsig.fmap.dal.swing.impl.searchpanel.AdvancedAttributeSelectionTreeModel.Node;
37
import org.gvsig.tools.ToolsLocator;
38
import org.gvsig.tools.dataTypes.CoercionException;
39
import org.gvsig.tools.dataTypes.DataTypesManager;
40
import org.gvsig.tools.exception.BaseException;
41
import org.gvsig.tools.swing.api.DropDown;
42
import org.gvsig.tools.swing.api.ToolsSwingLocator;
43
import org.gvsig.tools.swing.api.ToolsSwingManager;
44
import org.gvsig.tools.swing.api.windowmanager.Dialog;
45
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
46
import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2;
47
import org.gvsig.tools.util.LabeledValue;
48
import org.gvsig.tools.util.LabeledValueImpl;
49
import org.gvsig.tools.visitor.VisitCanceledException;
50
import org.gvsig.tools.visitor.Visitor;
51
import org.slf4j.Logger;
52
import org.slf4j.LoggerFactory;
53

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

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

    
65
        FeatureAttributeDescriptor attrdesc;
66
        private final FeatureStore store;
67

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

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

    
86
        public FeatureAttributeDescriptor getDescriptor() {
87
            return this.attrdesc;
88
        }
89

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

    
103
    }
104

    
105
    private FeatureStore store;
106
    private final JLabel lblFields;
107
    private final JLabel lblExtraFields;
108
    private final JLabel lblLogicalOperators;
109
    private final JLabel lblRelationalOperators;
110
    private final JComboBox cboValue;
111

    
112
    private DropDown ddnFields;
113
    private DropDown ddnLogicalOperators;
114
    private DropDown ddnRelationalOperators;
115

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

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

    
147
    private void initComponents() {
148
        try {
149
            ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
150
            this.lblExtraFields.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
151

    
152
            this.ddnFields = toolsSwingManager.createDropDown(lblFields);
153
            this.ddnRelationalOperators = toolsSwingManager.createDropDown(lblRelationalOperators);
154
            if (lblLogicalOperators != null) {
155
                this.ddnLogicalOperators = toolsSwingManager.createDropDown(lblLogicalOperators);
156
            }
157

    
158
            DefaultComboBoxModel modelRelationalOperators = new DefaultComboBoxModel();
159
            for (LabeledValue op : relationalOperators) {
160
                modelRelationalOperators.addElement(op);
161
            }
162
            this.ddnRelationalOperators.setModel(modelRelationalOperators);
163

    
164
            if (this.ddnLogicalOperators != null) {
165
                DefaultComboBoxModel modelLogicalOperators = new DefaultComboBoxModel();
166
                for (LabeledValue op : logicalOperators) {
167
                    modelLogicalOperators.addElement(op);
168
                }
169
                this.ddnLogicalOperators.setModel(modelLogicalOperators);
170
            }
171
            FeatureType featureType = store.getDefaultFeatureType();
172
            Search search = (Search) ToolsLocator.getComplementsManager().get(
173
                    Search.COMPLEMENT_MANE, featureType
174
            );
175
            List<FeatureAttributeDescriptor> orderedAttributes = search.getOrderedAttributes(
176
                    Search.BASIC_TYPES_FILTER,
177
                    Search.STR_INT_LONG_LABEL_ORDER,
178
                    20
179
            );
180
            DefaultComboBoxModel model = new DefaultComboBoxModel();
181
            for (FeatureAttributeDescriptor attrdesc : orderedAttributes) {
182
                model.addElement(new FeatureAttribute(this.store, attrdesc));
183
            }
184

    
185
            this.ddnFields.setModel(model);
186
            this.ddnFields.addItemListener(new ItemListener() {
187
                @Override
188
                public void itemStateChanged(ItemEvent e) {
189
                    if (e.getStateChange() == ItemEvent.SELECTED) {
190
                        doUpdateValuesList();
191
                    }
192

    
193
                }
194
            });
195

    
196
            this.lblExtraFields.addMouseListener(new MouseAdapter() {
197
                @Override
198
                public void mouseClicked(MouseEvent e) {
199
                    doSelectExtraField();
200
                }
201
            });
202
            clear();
203
        } catch (Exception ex) {
204
            throw new RuntimeException(ex);
205
        }
206
    }
207

    
208
    private FeatureType getFeatureType() {
209
        try {
210
            return this.store.getDefaultFeatureType();
211
        } catch (DataException ex) {
212
            return null;
213
        }
214
    }
215

    
216
    private void doSelectExtraField() {
217
        FeatureType featureType = this.getFeatureType();
218
        Search search = (Search) ToolsLocator.getComplementsManager().get(
219
                Search.COMPLEMENT_MANE, featureType
220
        );
221
        List<FeatureAttributeDescriptor> orderedAttributes = search.getOrderedAttributes(
222
                Search.BASIC_TYPES_FILTER,
223
                Search.LABEL_ORDER,
224
                -1
225
        );
226
        AdvancedAttributeSelectionTreeModel treeModel = new AdvancedAttributeSelectionTreeModel(
227
                this.store,
228
                orderedAttributes
229
        );
230
        final JTree tree = new JTree();
231
        tree.setCellRenderer(new AdvancedAttributeSelectionTreeCellRenderer());
232
        tree.setModel(treeModel);
233
        JScrollPane scrollpane = new JScrollPane(tree);
234
        scrollpane.setPreferredSize(new Dimension(400, 300));
235
        scrollpane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
236
        scrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
237

    
238
        WindowManager_v2 winManager = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
239
        final Dialog dialog = winManager.createDialog(
240
                scrollpane,
241
                "Select attribute",
242
                null,
243
                WindowManager_v2.BUTTONS_OK_CANCEL
244
        );
245
        dialog.addActionListener(new ActionListener() {
246
            @Override
247
            public void actionPerformed(ActionEvent e) {
248
                if (dialog.getAction() == WindowManager_v2.BUTTONS_OK) {
249
                    TreePath path = tree.getSelectionPath();
250
                    doAddAndSelect(path.getPath());
251
                }
252
            }
253
        });
254
        dialog.show(WindowManager.MODE.DIALOG);
255

    
256
    }
257

    
258
    private void doAddAndSelect(Object[] nodes) {
259
        ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
260
        ExpressionBuilder.Function list = builder.list();
261
        for (int i = 1; i < nodes.length; i++) {
262
            Node node = (Node) nodes[i];
263
            FeatureAttributeDescriptor attrdesc = node.getValue();
264
            list.parameter(builder.constant(attrdesc.getName()));
265
        }
266
        Node node = (Node) nodes[nodes.length - 1];
267
        FeatureStore theStore = node.getFeatureStore();
268
        FeatureAttributeDescriptor attrdesc = node.getValue();
269
        String storeFullName = theStore.getFullName();
270
        DefaultComboBoxModel<FeatureAttribute> model = (DefaultComboBoxModel) this.ddnFields.getModel();
271
        for (int i = 0; i < model.getSize(); i++) {
272
            FeatureAttribute attr = model.getElementAt(i);
273
            FeatureAttributeDescriptor attrdescN = attr.getDescriptor();
274
            if (StringUtils.equalsIgnoreCase(storeFullName, attrdescN.getStore().getFullName())
275
                    && StringUtils.equalsIgnoreCase(attrdesc.getName(), attrdescN.getName())) {
276
                this.setAttribute(i);
277
                return;
278
            }
279
        }
280
        String formula = builder.function(DataManager.FUNCTION_FOREING_VALUE, list).toString();
281
        String label = attrdesc.getLabel() + " [" + theStore.getName() + "]";
282
        if (StringUtils.equalsIgnoreCase(storeFullName, this.store.getFullName())) {
283
            label = attrdesc.getLabel();
284
            formula = attrdesc.getName();
285
        }
286
        FeatureAttribute attribute = new FeatureAttribute(theStore, attrdesc, label, formula);
287
        model.addElement(attribute);
288
        this.setAttribute(model.getSize() - 1);
289
    }
290

    
291
    public void clear() {
292
        this.ddnRelationalOperators.setSelectedIndex(0);
293
        if (this.ddnLogicalOperators != null) {
294
            this.ddnLogicalOperators.setSelectedIndex(0);
295
        }
296
        this.cboValue.setSelectedIndex(-1);
297
    }
298

    
299
    private void doUpdateValuesList() {
300
        final FeatureAttribute attribute = (FeatureAttribute) this.ddnFields.getSelectedItem();
301
        if (attribute == null) {
302
            return;
303
        }
304

    
305
        final List<Object> values = new ArrayList<>();
306
        final int limit = 60;
307
        final long timeLimit = System.currentTimeMillis() + limit * 1000;
308
        final DefaultComboBoxModel model = new DefaultComboBoxModel();
309
        this.setEnabled(false);
310
        Thread th = new Thread(new Runnable() {
311
            @Override
312
            public void run() {
313
                try {
314
                    FeatureSet set = attribute.getFeatureStore().getFeatureSet();
315
                    set.accept(new Visitor() {
316
                        @Override
317
                        public void visit(Object o) throws VisitCanceledException, BaseException {
318
                            Object value = ((Feature) o).get(attribute.getDescriptor().getName());
319
                            if (!values.contains(value)) {
320
                                values.add(value);
321
                            }
322
                            if (System.currentTimeMillis() > timeLimit) {
323
                                throw new VisitCanceledException();
324
                            }
325
                            if (values.size() > 1000) {
326
                                throw new VisitCanceledException();
327
                            }
328
                        }
329
                    });
330
                } catch (VisitCanceledException ex) {
331

    
332
                } catch (Exception ex) {
333
                    LOGGER.warn("Can't update list of values of '"+attribute.getLabel()+"'.", ex);
334
                }
335
                List<LabeledValue> elements = new ArrayList<>();
336
                if (!values.isEmpty()) {
337
                    LabeledValue[] availableValues = attribute.getDescriptor().getAvailableValues();
338
                    Map<String, String> availableValuesMap = new HashMap<>();
339
                    if (availableValues != null) {
340
                        for (LabeledValue availableValue : availableValues) {
341
                            availableValuesMap.put(
342
                                    Objects.toString(availableValue.getValue()),
343
                                    availableValue.getLabel()
344
                            );
345
                        }
346
                    }
347
                    elements.add(new LabeledValueImpl("", null));
348
                    for (Object value : values) {
349
                        String key = Objects.toString(value);
350
                        String label = availableValuesMap.getOrDefault(key, key);
351
                        elements.add(new LabeledValueImpl(label, value));
352
                    }
353
                    elements.sort(null);
354
                    
355
                }
356
                for (LabeledValue element : elements) {
357
                    model.addElement(element);
358
                }
359
                SwingUtilities.invokeLater(new Runnable() {
360
                    @Override
361
                    public void run() {
362
                        cboValue.setModel(model);
363
                        setEnabled(true);
364
                    }
365
                });
366
            }
367
        });
368
        th.start();
369
    }
370

    
371
    public void setEnabled(boolean enabled) {
372
        this.ddnFields.setEnabled(enabled);
373
        if( this.ddnLogicalOperators!=null ) {
374
            this.ddnLogicalOperators.setEnabled(enabled);
375
        }
376
        this.ddnRelationalOperators.setEnabled(enabled);
377
        this.lblExtraFields.setEnabled(enabled);
378
    }
379
    
380
    public String getRelationalOperator() {
381
        LabeledValue<String> op = (LabeledValue) this.ddnRelationalOperators.getSelectedItem();
382
        if (op == null) {
383
            return null;
384
        }
385
        return op.getValue();
386
    }
387

    
388
    public String getLogicalOperator() {
389
        if (this.ddnLogicalOperators == null) {
390
            return null;
391
        }
392
        LabeledValue<String> rel = (LabeledValue) this.ddnLogicalOperators.getSelectedItem();
393
        if (rel == null) {
394
            return null;
395
        }
396
        return rel.getValue();
397
    }
398

    
399
    public Object getValue() {
400
        final FeatureAttribute attribute = (FeatureAttribute) this.ddnFields.getSelectedItem();
401
        if (attribute == null) {
402
            return null;
403
        }
404
        Object v = this.cboValue.getSelectedItem();
405
        if (v == null) {
406
            return null;
407
        }
408
        if (v instanceof LabeledValue) {
409
            v = ((LabeledValue) v).getValue();
410
            if (v == null) {
411
                return null;
412
            }
413
        }
414
        if (v instanceof CharSequence) {
415
            if (StringUtils.isBlank((CharSequence) v)) {
416
                return null;
417
            }
418
        }
419
        DataTypesManager.Coercion coercion = attribute.getDescriptor().getDataType().getCoercion();
420
        try {
421
            return coercion.coerce(v);
422
        } catch (CoercionException ex) {
423
            return null;
424
        }
425
    }
426

    
427
    public boolean isAttributeAnExpression() {
428
        final FeatureAttribute attribute = (FeatureAttribute) this.ddnFields.getSelectedItem();
429
        if (attribute == null) {
430
            return false;
431
        }
432
        return attribute.isExpression();
433
    }
434

    
435
    public String getAttribute() {
436
        final FeatureAttribute attribute = (FeatureAttribute) this.ddnFields.getSelectedItem();
437
        if (attribute == null) {
438
            return null;
439
        }
440
        attribute.getDescriptor().recentUsed();
441
        return attribute.getValue();
442
    }
443

    
444
    public void setAttribute(String name) {
445
        ComboBoxModel<FeatureAttribute> model = this.ddnFields.getModel();
446
        for (int i = 0; i < model.getSize(); i++) {
447
            FeatureAttribute x = model.getElementAt(i);
448
            if (StringUtils.equalsIgnoreCase(name, x.getLabel())) {
449
                this.setAttribute(i);
450
                return;
451
            }
452
        }
453
        this.setAttribute(-1);
454
    }
455

    
456
    public void setAttribute(int index) {
457
        try {
458
            this.ddnFields.setSelectedIndex(index);
459
        } catch (Exception ex) {
460
            this.ddnFields.setSelectedIndex(-1);
461
        }
462
        doUpdateValuesList();
463
    }
464

    
465
};