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

History | View | Annotate | Download (17 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.List;
12
import javax.swing.Action;
13
import javax.swing.ImageIcon;
14
import javax.swing.JButton;
15
import javax.swing.JComponent;
16
import javax.swing.SwingUtilities;
17
import javax.swing.event.ListSelectionEvent;
18
import javax.swing.event.ListSelectionListener;
19
import javax.swing.table.AbstractTableModel;
20
import javax.swing.table.TableModel;
21
import org.apache.commons.io.FilenameUtils;
22
import org.apache.commons.lang.mutable.MutableObject;
23
import org.gvsig.expressionevaluator.Expression;
24
import org.gvsig.expressionevaluator.ExpressionBuilder;
25
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_AND;
26
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_OR;
27
import org.gvsig.expressionevaluator.ExpressionUtils;
28
import org.gvsig.expressionevaluator.swing.ExpressionEvaluatorSwingLocator;
29
import org.gvsig.expressionevaluator.swing.ExpressionEvaluatorSwingManager;
30
import org.gvsig.expressionevaluator.swing.ExpressionPickerController;
31
import org.gvsig.fmap.dal.complements.Search;
32
import org.gvsig.fmap.dal.exception.DataException;
33
import org.gvsig.fmap.dal.feature.Feature;
34
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
35
import org.gvsig.fmap.dal.feature.FeatureStore;
36
import org.gvsig.fmap.dal.feature.FeatureType;
37
import org.gvsig.fmap.dal.swing.DALSwingLocator;
38
import org.gvsig.fmap.dal.swing.searchpanel.FeatureStoreSearchPanel;
39
import org.gvsig.tools.ToolsLocator;
40
import org.gvsig.tools.swing.api.ActionListenerSupport;
41
import org.gvsig.tools.swing.api.ToolsSwingLocator;
42
import org.gvsig.tools.swing.icontheme.IconTheme;
43
import org.slf4j.Logger;
44
import org.slf4j.LoggerFactory;
45

    
46
/**
47
 *
48
 * @author jjdelcerro
49
 */
50
@SuppressWarnings("UseSpecificCatch")
51
public class DefaultSearchPanel
52
        extends DefaultSearchPanelView
53
        implements FeatureStoreSearchPanel {
54

    
55
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSearchPanel.class);
56
    private Expression currentSearch;
57

    
58
    private class FeaturesTableModel extends AbstractTableModel {
59

    
60
        private final List<Feature> features;
61
        private final List<String> columnNames;
62
        private final FeatureType featureType;
63

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

    
85
        public List<Feature> getFeatures() {
86
            return this.features;
87
        }
88

    
89
        @Override
90
        public int getRowCount() {
91
            if (this.features == null) {
92
                return 0;
93
            }
94
            return this.features.size();
95
        }
96

    
97
        @Override
98
        public int getColumnCount() {
99
            return this.columnNames.size();
100
        }
101

    
102
        @Override
103
        public String getColumnName(int columnIndex) {
104
            String attrName = this.columnNames.get(columnIndex);
105
            if (this.featureType == null) {
106
                return attrName;
107
            }
108
            FeatureAttributeDescriptor attrdesc = this.featureType.getAttributeDescriptor(attrName);
109
            if (attrdesc == null) {
110
                return "C" + columnIndex;
111
            }
112
            return attrdesc.getLabel();
113
        }
114

    
115
        @Override
116
        public Class<?> getColumnClass(int columnIndex) {
117
            if (this.featureType == null) {
118
                return String.class;
119
            }
120
            String attrName = this.columnNames.get(columnIndex);
121
            FeatureAttributeDescriptor attrdesc = this.featureType.getAttributeDescriptor(attrName);
122
            if (attrdesc == null) {
123
                return String.class;
124
            }
125
            return attrdesc.getDataType().getDefaultClass();
126
        }
127

    
128
        @Override
129
        public boolean isCellEditable(int rowIndex, int columnIndex) {
130
            return false;
131
        }
132

    
133
        @Override
134
        public Object getValueAt(int rowIndex, int columnIndex) {
135
            if (this.features == null) {
136
                return null;
137
            }
138
            Feature feature = this.features.get(rowIndex);
139
            String attrName = this.columnNames.get(columnIndex);
140
            try {
141
                return feature.get(attrName);
142
            } catch (Throwable th) {
143
                return null;
144
            }
145
        }
146

    
147
        @Override
148
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
149

    
150
        }
151
    }
152

    
153
    private final FeatureStore store;
154
    private final ActionListenerSupport acctionListeners;
155
    private final List<SearchFieldController> searchFields;
156
    private ExpressionPickerController advancedExpression;
157
    private final List<Action> actions;
158

    
159
    public DefaultSearchPanel(FeatureStore store) {
160
        this.store = store;
161
        this.acctionListeners = ToolsSwingLocator.getToolsSwingManager().createActionListenerSupport();
162
        this.searchFields = new ArrayList<>();
163
        this.actions = new ArrayList<>();
164
        this.initComponents();
165
    }
166

    
167
    @Override
168
    public JComponent asJComponent() {
169
        return this;
170
    }
171

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

    
191
    @Override
192
    public void addActionListener(ActionListener listener) {
193
        this.acctionListeners.addActionListener(listener);
194
    }
195

    
196
    @Override
197
    public ActionListener[] getActionListeners() {
198
        return this.acctionListeners.getActionListeners();
199
    }
200

    
201
    @Override
202
    public void removeActionListener(ActionListener listener) {
203
        this.acctionListeners.removeActionListener(listener);
204
    }
205

    
206
    @Override
207
    public void removeAllActionListener() {
208
        this.acctionListeners.removeAllActionListener();
209
    }
210

    
211
    @Override
212
    public void fireActionEvent(ActionEvent event) {
213
        this.acctionListeners.fireActionEvent(event);
214
    }
215

    
216
    @Override
217
    public boolean hasActionListeners() {
218
        return this.acctionListeners.hasActionListeners();
219
    }
220

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

    
275
        ExpressionEvaluatorSwingManager expressionSwingManager = ExpressionEvaluatorSwingLocator.getManager();
276
        this.advancedExpression = expressionSwingManager.createExpressionPickerController(
277
                txtAdvancedExpression, 
278
                btnAdvancedExpression,
279
                btnAdvancedExpressionHistory,
280
                btnAdvancedExpressionBookmarks
281
        );
282

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

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

    
309
        doSearch(null);
310
    }
311

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

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

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

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

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

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

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

    
443
    @Override
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
}