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 / DefaultSearchPanel.java @ 44263

History | View | Annotate | Download (17.2 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.FlowLayout;
6
import java.awt.event.ActionEvent;
7
import java.awt.event.ActionListener;
8
import java.net.URL;
9
import java.util.ArrayList;
10
import java.util.Collection;
11
import java.util.LinkedHashMap;
12
import java.util.List;
13
import java.util.Map;
14
import javax.swing.Action;
15
import javax.swing.ImageIcon;
16
import javax.swing.JButton;
17
import javax.swing.JComponent;
18
import javax.swing.SwingUtilities;
19
import javax.swing.event.ListSelectionEvent;
20
import javax.swing.event.ListSelectionListener;
21
import javax.swing.table.AbstractTableModel;
22
import javax.swing.table.TableModel;
23
import org.apache.commons.io.FilenameUtils;
24
import org.apache.commons.lang.mutable.MutableObject;
25
import org.gvsig.expressionevaluator.Expression;
26
import org.gvsig.expressionevaluator.ExpressionBuilder;
27
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_AND;
28
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_OR;
29
import org.gvsig.expressionevaluator.ExpressionUtils;
30
import org.gvsig.expressionevaluator.swing.ExpressionEvaluatorSwingLocator;
31
import org.gvsig.expressionevaluator.swing.ExpressionEvaluatorSwingManager;
32
import org.gvsig.expressionevaluator.swing.ExpressionPickerController;
33
import org.gvsig.fmap.dal.complements.Search;
34
import org.gvsig.fmap.dal.exception.DataException;
35
import org.gvsig.fmap.dal.feature.Feature;
36
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
37
import org.gvsig.fmap.dal.feature.FeatureStore;
38
import org.gvsig.fmap.dal.feature.FeatureType;
39
import org.gvsig.fmap.dal.swing.DALSwingLocator;
40
import org.gvsig.fmap.dal.swing.impl.searchpanel.actions.SelectionAddAction;
41
import org.gvsig.fmap.dal.swing.impl.searchpanel.actions.SelectionFilterAction;
42
import org.gvsig.fmap.dal.swing.impl.searchpanel.actions.SelectionSetAction;
43
import org.gvsig.fmap.dal.swing.impl.searchpanel.actions.ShowFormAction;
44
import org.gvsig.fmap.dal.swing.searchpanel.FeatureStoreSearchPanel;
45
import org.gvsig.tools.ToolsLocator;
46
import org.gvsig.tools.swing.api.ActionListenerSupport;
47
import org.gvsig.tools.swing.api.ToolsSwingLocator;
48
import org.gvsig.tools.swing.icontheme.IconTheme;
49
import org.slf4j.Logger;
50
import org.slf4j.LoggerFactory;
51

    
52
/**
53
 *
54
 * @author jjdelcerro
55
 */
56
@SuppressWarnings("UseSpecificCatch")
57
public class DefaultSearchPanel
58
        extends DefaultSearchPanelView
59
        implements FeatureStoreSearchPanel {
60

    
61
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSearchPanel.class);
62
    private Expression currentSearch;
63

    
64
    private class FeaturesTableModel extends AbstractTableModel {
65

    
66
        private final List<Feature> features;
67
        private final List<String> columnNames;
68
        private final FeatureType featureType;
69

    
70
        public FeaturesTableModel(FeatureType featureType, List<String> columnNames, List<Feature> features) {
71
            this.features = features;
72
            this.featureType = featureType;
73
            if (columnNames == null || columnNames.isEmpty()) {
74
                this.columnNames = new ArrayList<>();
75
                Search search = (Search) ToolsLocator.getComplementsManager().get(
76
                        Search.COMPLEMENT_MANE, featureType
77
                );
78
                List<FeatureAttributeDescriptor> attributos = search.getOrderedAttributes(
79
                        Search.BASIC_TYPES_FILTER,
80
                        Search.STR_INT_LONG_LABEL_ORDER,
81
                        12
82
                );
83
                for (FeatureAttributeDescriptor attrdesc : attributos) {
84
                    this.columnNames.add(attrdesc.getName());
85
                }
86
            } else {
87
                this.columnNames = columnNames;
88
            }
89
        }
90

    
91
        public List<Feature> getFeatures() {
92
            return this.features;
93
        }
94

    
95
        @Override
96
        public int getRowCount() {
97
            if (this.features == null) {
98
                return 0;
99
            }
100
            return this.features.size();
101
        }
102

    
103
        @Override
104
        public int getColumnCount() {
105
            return this.columnNames.size();
106
        }
107

    
108
        @Override
109
        public String getColumnName(int columnIndex) {
110
            String attrName = this.columnNames.get(columnIndex);
111
            if (this.featureType == null) {
112
                return attrName;
113
            }
114
            FeatureAttributeDescriptor attrdesc = this.featureType.getAttributeDescriptor(attrName);
115
            if (attrdesc == null) {
116
                return "C" + columnIndex;
117
            }
118
            return attrdesc.getLabel();
119
        }
120

    
121
        @Override
122
        public Class<?> getColumnClass(int columnIndex) {
123
            if (this.featureType == null) {
124
                return String.class;
125
            }
126
            String attrName = this.columnNames.get(columnIndex);
127
            FeatureAttributeDescriptor attrdesc = this.featureType.getAttributeDescriptor(attrName);
128
            if (attrdesc == null) {
129
                return String.class;
130
            }
131
            return attrdesc.getDataType().getDefaultClass();
132
        }
133

    
134
        @Override
135
        public boolean isCellEditable(int rowIndex, int columnIndex) {
136
            return false;
137
        }
138

    
139
        @Override
140
        public Object getValueAt(int rowIndex, int columnIndex) {
141
            if (this.features == null) {
142
                return null;
143
            }
144
            Feature feature = this.features.get(rowIndex);
145
            String attrName = this.columnNames.get(columnIndex);
146
            try {
147
                return feature.get(attrName);
148
            } catch (Throwable th) {
149
                return null;
150
            }
151
        }
152

    
153
        @Override
154
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
155

    
156
        }
157
    }
158

    
159
    private final FeatureStore store;
160
    private final ActionListenerSupport acctionListeners;
161
    private final List<SearchFieldController> searchFields;
162
    private ExpressionPickerController advancedExpression;
163
    private List<Action> actions;
164

    
165
    public DefaultSearchPanel(FeatureStore store) {
166
        this.store = store;
167
        this.acctionListeners = ToolsSwingLocator.getToolsSwingManager().createActionListenerSupport();
168
        this.searchFields = new ArrayList<>();
169
        this.actions = new ArrayList<>();
170
        this.initComponents();
171
    }
172

    
173
    @Override
174
    public JComponent asJComponent() {
175
        return this;
176
    }
177

    
178
    private void addActions() {
179
        this.pnlActions.removeAll();
180
        this.pnlActions.setLayout(new FlowLayout(FlowLayout.TRAILING, 2, 2));
181
        Collection<ActionFactory> factories = DALSwingLocator.getSwingManager().getFeatureStoreSearchActions();
182
        for (ActionFactory factory : factories) {
183
            Action action = factory.createAction(this);
184
            this.actions.add(action);
185
            JButton button = new JButton(action);
186
//            button.setBorder(BorderFactory.createEmptyBorder());
187
            button.setBorderPainted(false);
188
            button.setFocusPainted(false);
189
            button.setContentAreaFilled(false);
190
            button.setCursor(new Cursor(Cursor.HAND_CURSOR));
191
            this.pnlActions.add(button);
192
        }
193
        this.pnlActions.revalidate();
194
        this.pnlActions.repaint();
195
    }
196

    
197
    @Override
198
    public void addActionListener(ActionListener listener) {
199
        this.acctionListeners.addActionListener(listener);
200
    }
201

    
202
    @Override
203
    public ActionListener[] getActionListeners() {
204
        return this.acctionListeners.getActionListeners();
205
    }
206

    
207
    @Override
208
    public void removeActionListener(ActionListener listener) {
209
        this.acctionListeners.removeActionListener(listener);
210
    }
211

    
212
    @Override
213
    public void removeAllActionListener() {
214
        this.acctionListeners.removeAllActionListener();
215
    }
216

    
217
    @Override
218
    public void fireActionEvent(ActionEvent event) {
219
        this.acctionListeners.fireActionEvent(event);
220
    }
221

    
222
    @Override
223
    public boolean hasActionListeners() {
224
        return this.acctionListeners.hasActionListeners();
225
    }
226

    
227
    private void initComponents() {
228
        SearchFieldController controller = new SearchFieldController(
229
                store,
230
                lblField1,
231
                lblExtraFields1,
232
                lblRelationalOperator1,
233
                cboValue1,
234
                lblLogicalOperators1
235
        );
236
        this.searchFields.add(controller);
237
        controller = new SearchFieldController(
238
                store,
239
                lblField2,
240
                lblExtraFields2,
241
                lblRelationalOperator2,
242
                cboValue2,
243
                lblLogicalOperators2
244
        );
245
        this.searchFields.add(controller);
246
        controller = new SearchFieldController(
247
                store,
248
                lblField3,
249
                lblExtraFields3,
250
                lblRelationalOperator3,
251
                cboValue3,
252
                lblLogicalOperators3
253
        );
254
        this.searchFields.add(controller);
255
        controller = new SearchFieldController(
256
                store,
257
                lblField4,
258
                lblExtraFields4,
259
                lblRelationalOperator4,
260
                cboValue4,
261
                null
262
        );
263
        this.searchFields.add(controller);
264
        try {
265
            Search search = (Search) ToolsLocator.getComplementsManager().get(
266
                    Search.COMPLEMENT_MANE, this.store.getDefaultFeatureType()
267
            );
268
            List<FeatureAttributeDescriptor> orderedAttributes = search.getOrderedAttributes(
269
                    Search.BASIC_TYPES_FILTER,
270
                    Search.STR_INT_LONG_LABEL_ORDER,
271
                    5
272
            );
273
            int n = 0;
274
            for (SearchFieldController searchField : searchFields) {
275
                searchField.setAttribute(orderedAttributes.get(n++).getName());
276
            }
277
        } catch (DataException ex) {
278
            LOGGER.warn("Can't determine order of attributes", ex);
279
        }
280

    
281
        ExpressionEvaluatorSwingManager expressionSwingManager = ExpressionEvaluatorSwingLocator.getManager();
282
        this.advancedExpression = expressionSwingManager.createExpressionPickerController(txtAdvancedExpression, btnAdvancedExpression);
283

    
284
        this.btnSearch.addActionListener(new ActionListener() {
285
            @Override
286
            public void actionPerformed(ActionEvent e) {
287
                doSearch();
288
            }
289
        });
290

    
291
        this.tblResults.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
292
            @Override
293
            public void valueChanged(ListSelectionEvent e) {
294
                for (Action action : actions) {
295
                    if( action instanceof ListSelectionListener) {
296
                        ((ListSelectionListener) action).valueChanged(e);
297
                    }
298
                }
299
            }
300
        });
301
        this.btnClear.addActionListener(new ActionListener() {
302
            @Override
303
            public void actionPerformed(ActionEvent e) {
304
                clear();
305
            }
306
        });
307
        addActions();
308
        this.setPreferredSize(new Dimension(700, 450));
309

    
310
        doSearch(null);
311
    }
312

    
313
    @Override
314
    public void setEnabled(boolean enabled) {
315
        for (SearchFieldController searchField : searchFields) {
316
            searchField.setEnabled(enabled);
317
        }
318
        this.btnClear.setEnabled(enabled);
319
        this.btnSearch.setEnabled(enabled);
320
        this.advancedExpression.setEnabled(enabled);
321
        for (Action action : actions) {
322
            action.setEnabled(enabled);
323
        }
324
    }
325

    
326
    public void clear() {
327
        for (SearchFieldController searchField : searchFields) {
328
            searchField.clear();
329
        }
330
        this.advancedExpression.set(null);
331
    }
332

    
333
    private void doSearch() {
334
        int searchMode = this.tabSearchMode.getSelectedIndex();
335
        if (searchMode == 1) { // Avanzada
336
            Expression filter = this.advancedExpression.get();
337
            if (ExpressionUtils.isPhraseEmpty(filter)) {
338
                return;
339
            }
340
            doSearch(filter);
341
            return;
342
        }
343

    
344
        ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
345
        String relational = OPERATOR_OR;
346
        for (SearchFieldController searchField : searchFields) {
347
            if (searchField.getAttribute() != null && searchField.getValue() != null) {
348
                ExpressionBuilder.BinaryOperator cond = builder.binaryOperator(
349
                        searchField.getRelationalOperator(),
350
                        searchField.isAttributeAnExpression()
351
                        ? builder.custom(searchField.getAttribute())
352
                        : builder.column(searchField.getAttribute()),
353
                        builder.constant(searchField.getValue())
354
                );
355
                if (relational.equals(OPERATOR_AND)) {
356
                    builder.and(cond);
357
                } else {
358
                    builder.or(cond);
359
                }
360
                relational = searchField.getLogicalOperator();
361
            }
362
        }
363
        if (builder.isEmpty()) {
364
            doSearch(null);
365
            return;
366
        }
367
        this.txtAdvancedExpression.setText(builder.toString());
368
        doSearch(ExpressionUtils.createExpression(builder.toString()));
369
    }
370

    
371
    private void doSearch(final Expression exp) {
372
        final MutableObject model = new MutableObject(null);
373
        
374
        lblMsg.setText("Searching...");
375
        setEnabled(false);
376
        Thread th = new Thread(new Runnable() {
377
            @Override
378
            public void run() {
379
                try {
380
                    final List<Feature> features;
381
                    if (exp == null) {
382
                        features = store.getFeatures();
383
                    } else {
384
                        features = store.getFeatures(exp);
385
                    }
386
                    currentSearch = exp;
387
                    model.setValue( new FeaturesTableModel(
388
                            store.getDefaultFeatureType(),
389
                            null,
390
                            features
391
                        )
392
                    );
393
                } catch (DataException ex) {
394
                    LOGGER.warn("Can't get features or create table model",ex);
395
                } finally {
396
                    SwingUtilities.invokeLater(new Runnable() {
397
                        @Override
398
                        public void run() {
399
                            TableModel m = (TableModel) model.getValue();
400
                            tblResults.setModel(m);
401
                            lblMsg.setText(String.format("%d elementos", m.getRowCount()));
402
                            setEnabled(true);
403
                        }
404
                    });
405
                }
406
            }
407
        });
408
        th.start();
409
    }
410

    
411
    @Override
412
    public Expression getCurrentSearch() {
413
        return this.currentSearch;
414
    }
415

    
416
    @Override
417
    public Expression getSearchForSelectedFeature() {
418
        int selectedRow = this.tblResults.getSelectedRow();
419
        if (selectedRow < 0) {
420
            return null;
421
        }
422
        try {
423
            List<Feature> features = ((FeaturesTableModel) this.tblResults.getModel()).getFeatures();
424
            Feature feature = features.get(selectedRow);
425
            
426
            ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
427
            FeatureType ftype = this.store.getDefaultFeatureType();
428
            for (FeatureAttributeDescriptor attrdesc : ftype.getPrimaryKey()) {
429
                builder.and(
430
                        builder.eq(
431
                                builder.column(attrdesc.getName()),
432
                                builder.constant(feature.get(attrdesc.getName()))
433
                        )
434
                );
435
            }
436
            Expression filter = ExpressionUtils.createExpression(builder.toString());
437
            return filter;
438
        } catch (Exception ex) {
439
            LOGGER.warn("Can't build search for the selected feature.", ex);
440
            return null;
441
        }
442
    }
443

    
444
    public FeatureStore getStore() {
445
        return store;
446
    }
447
    
448
    @Override
449
    public ImageIcon loadImage(String imageName) {
450
        String name = FilenameUtils.getBaseName(imageName);
451
        IconTheme theme = ToolsSwingLocator.getIconThemeManager().getDefault();
452
        if (theme.exists(name)) {
453
            return theme.get(name);
454
        }
455
        URL url = this.getClass().getResource(name + ".png");
456
        if (url == null) {
457
            return null;
458
        }
459
        return new ImageIcon(url);
460
    }
461

    
462
    public static void selfRegister() {
463
        String[][] iconNames = new String[][]{
464
            new String[]{"dalswing", "featurestore-column"},
465
            new String[]{"dalswing", "featurestore-foreing-key"},
466
            new String[]{"dalswing", "featurestore-table"},
467
            new String[]{"dalswing", "search-action-showform"},
468
            new String[]{"dalswing", "search-action-select"},
469
            new String[]{"dalswing", "search-action-select-add"},
470
            new String[]{"dalswing", "search-action-select-filter"}
471
        };
472
        IconTheme theme = ToolsSwingLocator.getIconThemeManager().getCurrent();
473
        for (String[] icon : iconNames) {
474
            URL url = DefaultSearchPanel.class.getResource(icon[1] + ".png");
475
            theme.registerDefault("DALSwing", icon[0], icon[1], null, url);
476
        }
477

    
478
    }
479

    
480
    @Override
481
    public int getSelectedFeatureCount() {
482
        return this.tblResults.getSelectedRowCount();
483
    }
484
    
485
}