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

History | View | Annotate | Download (19.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.HashMap;
12
import java.util.List;
13
import java.util.Map;
14
import javax.swing.Action;
15
import javax.swing.BorderFactory;
16
import javax.swing.ImageIcon;
17
import javax.swing.JButton;
18
import javax.swing.JComponent;
19
import javax.swing.SwingUtilities;
20
import javax.swing.event.ListSelectionEvent;
21
import javax.swing.event.ListSelectionListener;
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.Code;
26
import org.gvsig.expressionevaluator.Expression;
27
import org.gvsig.expressionevaluator.ExpressionBuilder;
28
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_AND;
29
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_OR;
30
import org.gvsig.expressionevaluator.ExpressionUtils;
31
import org.gvsig.expressionevaluator.swing.ExpressionEvaluatorSwingLocator;
32
import org.gvsig.expressionevaluator.swing.ExpressionEvaluatorSwingManager;
33
import org.gvsig.expressionevaluator.swing.ExpressionPickerController;
34
import org.gvsig.fmap.dal.DataStore;
35
import org.gvsig.fmap.dal.complements.Search;
36
import org.gvsig.fmap.dal.exception.DataException;
37
import org.gvsig.fmap.dal.feature.Feature;
38
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
39
import org.gvsig.fmap.dal.feature.FeatureStore;
40
import org.gvsig.fmap.dal.feature.FeatureType;
41
import org.gvsig.fmap.dal.swing.AbstractDALActionFactory.AbstractDALActionContext;
42
import org.gvsig.fmap.dal.swing.DALActionFactory;
43
import org.gvsig.fmap.dal.swing.DALSwingLocator;
44
import org.gvsig.fmap.dal.swing.impl.featuretable.SimpleFeaturesTableModel;
45
import org.gvsig.fmap.dal.swing.searchpanel.FeatureStoreSearchPanel;
46
import org.gvsig.tools.ToolsLocator;
47
import org.gvsig.tools.swing.api.ActionListenerSupport;
48
import org.gvsig.tools.swing.api.ToolsSwingLocator;
49
import org.gvsig.tools.swing.icontheme.IconTheme;
50
import org.slf4j.Logger;
51
import org.slf4j.LoggerFactory;
52

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

    
62
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSearchPanel.class);
63
    private Expression currentSearch;
64
    
65
    private class ActionButtons {
66
        
67
        private final DALActionFactory factory;
68
        private final Action action;
69
        private final JButton button;
70
        
71
        public ActionButtons(DALActionFactory factory, Action action, JButton button) {
72
            this.factory = factory;
73
            this.action = action;
74
            this.button = button;
75
        }
76
    }
77

    
78
    public static class SearchActionContext extends AbstractDALActionContext {
79

    
80
        private final DefaultSearchPanel panel;
81
        
82
        public SearchActionContext(DefaultSearchPanel panel) {
83
            super(FeatureStoreSearchPanel.ACTION_CONTEXT_NAME);
84
            this.panel = panel;
85
        }
86
        
87
        @Override
88
        public DataStore getStore() {
89
            return this.panel.getStore();
90
        }
91

    
92
        @Override
93
        public Expression getFilter() {
94
            return this.panel.getCurrentSearch();
95
        }
96

    
97
        @Override
98
        public JComponent getActionButton(String actionName) {
99
            return this.panel.getActionButton(actionName);
100
        }
101
        
102
        @Override
103
        public int getSelectedsCount() {
104
            return this.panel.getSelectedFeatureCount();
105
        }
106
        
107
        @Override
108
        public Expression getFilterForSelecteds() {
109
            return this.panel.getSearchForSelectedFeature();
110
        }
111
    }
112
    
113
    private final FeatureStore store;
114
    private final ActionListenerSupport acctionListeners;
115
    private List<SearchFieldController> searchFields;
116
    private ExpressionPickerController advancedExpression;
117
    private final Map<String, ActionButtons> actions;
118
    private boolean showActions = true;
119
    private int maxSearhFields = 4;
120

    
121
    public DefaultSearchPanel(FeatureStore store) {
122
        this.store = store;
123
        this.acctionListeners = ToolsSwingLocator.getToolsSwingManager().createActionListenerSupport();
124
        this.searchFields = null;
125
        this.actions = new HashMap<>();
126
    }
127

    
128
    @Override
129
    public JComponent asJComponent() {
130
        if( this.searchFields==null ) {
131
            this.initComponents();
132
        }
133
        return this;
134
    }
135

    
136
    private void addActions() {
137
        if( !this.showActions ) {
138
            return;
139
        }
140
        this.pnlActions.removeAll();
141
        this.pnlActions.setLayout(new FlowLayout(FlowLayout.TRAILING, 8, 4));
142
        SearchActionContext actionContext = new SearchActionContext(this);
143
        Collection<DALActionFactory> factories = DALSwingLocator.getSwingManager().getStoreActions();
144
        for (DALActionFactory factory : factories) {
145
            Action action = factory.createAction(actionContext);
146
            JButton button = new JButton(action);
147
            this.actions.put(factory.getName(), new ActionButtons(factory, action, button));
148
            button.setBorder(BorderFactory.createEmptyBorder());
149
            button.setBorderPainted(false);
150
            button.setFocusPainted(false);
151
            button.setContentAreaFilled(false);
152
            button.setCursor(new Cursor(Cursor.HAND_CURSOR));
153
            this.pnlActions.add(button);
154
        }
155
        this.pnlActions.revalidate();
156
        this.pnlActions.repaint();
157
    }
158

    
159
    @Override
160
    public void addActionListener(ActionListener listener) {
161
        this.acctionListeners.addActionListener(listener);
162
    }
163

    
164
    @Override
165
    public ActionListener[] getActionListeners() {
166
        return this.acctionListeners.getActionListeners();
167
    }
168

    
169
    @Override
170
    public void removeActionListener(ActionListener listener) {
171
        this.acctionListeners.removeActionListener(listener);
172
    }
173

    
174
    @Override
175
    public void removeAllActionListener() {
176
        this.acctionListeners.removeAllActionListener();
177
    }
178

    
179
    @Override
180
    public void fireActionEvent(ActionEvent event) {
181
        this.acctionListeners.fireActionEvent(event);
182
    }
183

    
184
    @Override
185
    public boolean hasActionListeners() {
186
        return this.acctionListeners.hasActionListeners();
187
    }
188

    
189
    private void initComponents() {
190
        this.searchFields = new ArrayList<>();
191
        SearchFieldController controller = new SearchFieldController(
192
                store,
193
                lblField1,
194
                lblExtraFields1,
195
                lblRelationalOperator1,
196
                cboValue1,
197
                lblLogicalOperators1
198
        );
199
        this.searchFields.add(controller);
200
        controller = new SearchFieldController(
201
                store,
202
                lblField2,
203
                lblExtraFields2,
204
                lblRelationalOperator2,
205
                cboValue2,
206
                lblLogicalOperators2
207
        );
208
        this.searchFields.add(controller);
209
        controller = new SearchFieldController(
210
                store,
211
                lblField3,
212
                lblExtraFields3,
213
                lblRelationalOperator3,
214
                cboValue3,
215
                lblLogicalOperators3
216
        );
217
        this.searchFields.add(controller);
218
        controller = new SearchFieldController(
219
                store,
220
                lblField4,
221
                lblExtraFields4,
222
                lblRelationalOperator4,
223
                cboValue4,
224
                null
225
        );
226
        this.searchFields.add(controller);
227
        try {
228
            Search search = (Search) ToolsLocator.getComplementsManager().get(
229
                    Search.COMPLEMENT_MANE, this.store.getDefaultFeatureType()
230
            );
231
            List<Search.OrderedAttribute> orderedAttributes = search.getOrderedAttributes(
232
                    Search.BASIC_TYPES_FILTER,
233
                    Search.STR_INT_LONG_LABEL_ORDER,
234
                    5
235
            );
236
            this.maxSearhFields = Integer.min(orderedAttributes.size(), 4);
237
            int n = 0;
238
            for (SearchFieldController searchField : searchFields) {
239
                if( n<this.maxSearhFields ) {
240
                    searchField.setAttribute(orderedAttributes.get(n++).getDescriptor().getName());
241
                } else {
242
                    searchField.setEnabled(false);
243
                }
244
            }
245
        } catch (DataException ex) {
246
            LOGGER.warn("Can't determine order of attributes", ex);
247
        }
248

    
249
        ExpressionEvaluatorSwingManager expressionSwingManager = ExpressionEvaluatorSwingLocator.getManager();
250
        this.advancedExpression = expressionSwingManager.createExpressionPickerController(
251
                txtAdvancedExpression, 
252
                btnAdvancedExpression,
253
                btnAdvancedExpressionHistory,
254
                btnAdvancedExpressionBookmarks
255
        );
256
        this.advancedExpression.addElement(
257
            DALSwingLocator.getSwingManager().createFeatureStoreElement(store)
258
        );
259

    
260
        this.btnSearch.addActionListener(new ActionListener() {
261
            @Override
262
            public void actionPerformed(ActionEvent e) {
263
                doSearch();
264
            }
265
        });
266

    
267
        this.tblResults.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
268
            @Override
269
            public void valueChanged(ListSelectionEvent e) {
270
                for (ActionButtons actionButton : actions.values()) {
271
                    if( actionButton.action instanceof ListSelectionListener) {
272
                        ((ListSelectionListener) actionButton.action).valueChanged(e);
273
                    }
274
                }
275
            }
276
        });
277
        this.btnClear.addActionListener(new ActionListener() {
278
            @Override
279
            public void actionPerformed(ActionEvent e) {
280
                clear();
281
            }
282
        });
283
        addActions();
284
        this.setPreferredSize(new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT));
285

    
286
        doSearch(null);
287
    }
288

    
289
    @Override
290
    public void setEnabled(boolean enabled) {
291
        if( this.searchFields==null ) {
292
            initComponents();
293
        }
294
        int n=0;
295
        for (SearchFieldController searchField : searchFields) {
296
            if( n<this.maxSearhFields ) {
297
                searchField.setEnabled(enabled);
298
            } else {
299
                searchField.setEnabled(false);
300
            }
301
            n++;
302
        }
303
        this.btnClear.setEnabled(enabled);
304
        this.btnSearch.setEnabled(enabled);
305
        this.advancedExpression.setEnabled(enabled);
306
        for (ActionButtons actionButton : actions.values()) {
307
            actionButton.action.setEnabled(enabled);
308
        }
309
    }
310

    
311
    public void clear() {
312
        if( this.searchFields==null ) {
313
            return;
314
        }
315
        for (SearchFieldController searchField : searchFields) {
316
            searchField.clear();
317
        }
318
        this.advancedExpression.set(null);
319
    }
320

    
321
    @Override
322
    public Expression getFilter() {
323
        Expression filter;
324
        int searchMode = this.tabSearchMode.getSelectedIndex();
325
        if (searchMode == 1) { // Avanzada
326
            filter = this.advancedExpression.get();
327
        } else {
328
            ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
329
            String relational = OPERATOR_OR;
330
            for (SearchFieldController searchField : searchFields) {
331
                if (searchField.getAttribute() != null && searchField.getValue() != null) {
332
                    ExpressionBuilder.BinaryOperator cond = builder.binaryOperator(
333
                            searchField.getRelationalOperator(),
334
                            searchField.isAttributeAnExpression()
335
                            ? builder.custom(searchField.getAttribute())
336
                            : builder.column(searchField.getAttribute()),
337
                            builder.constant(searchField.getValue())
338
                    );
339
                    if (relational.equals(OPERATOR_AND)) {
340
                        builder.and(cond);
341
                    } else {
342
                        builder.or(cond);
343
                    }
344
                    relational = searchField.getLogicalOperator();
345
                }
346
            }
347
            if (builder.isEmpty()) {
348
                filter = null;
349
            } else {
350
                filter = ExpressionUtils.createExpression(builder.toString());
351
            }
352
        }
353
        if (ExpressionUtils.isPhraseEmpty(filter)) {
354
            return null;
355
        }
356
        return filter;
357
    }
358
    
359
    private void doSearch() {
360
        Expression filter = this.getFilter();
361
        doSearch(filter);
362
    }
363

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

    
404
    @Override
405
    public Expression getCurrentSearch() {
406
        return this.currentSearch;
407
    }
408

    
409
    @Override
410
    public boolean setFilter(Expression filter) {
411
        try {
412
            if( this.advancedExpression==null ) {
413
                this.initComponents();
414
            }
415
            if( ExpressionUtils.isPhraseEmpty(filter) ) {
416
                this.clear();
417
                return true;
418
            }
419
            this.advancedExpression.set(filter);
420
            this.tabSearchMode.setSelectedIndex(1);
421
            
422
            Code code = filter.getCode();
423
            if( code.code()==Code.CALLER) {
424
                SearchFieldController searchField = this.searchFields.get(0);
425
                Code.Caller caller = (Code.Caller)code;
426
                if( searchField.isAValidRelationOperator(caller.name())) {
427
                    Code op1 = caller.parameters().get(0);
428
                    Code op2 = caller.parameters().get(1);
429
                    if( op1.code()==Code.IDENTIFIER && op2.code()==Code.CONSTANT ) {
430
                        if( searchField.setAttribute(((Code.Identifier)op1).name())>=0 ) {
431
                            searchField.setRelationalOperator(caller.name());
432
                            searchField.setValue(((Code.Constant)op2).value());
433
                            this.tabSearchMode.setSelectedIndex(0);
434
                        }
435
                    }
436
                }
437
            }
438
            SimpleFeaturesTableModel model = new SimpleFeaturesTableModel(this.getStore());
439
            tblResults.setModel(model);
440
            lblMsg.setText("");
441
            return true;
442
        } catch(Exception ex) {
443
            LOGGER.warn("Can't set current search", ex);
444
            return false;
445
        }
446
    }
447
   
448
    @Override
449
    public void setCurrentSearch(Expression filter) {
450
        if( this.setFilter(filter) ) {
451
            doSearch();
452
        }
453
    }
454
    
455
    @Override
456
    public Expression getSearchForSelectedFeature() {
457
        if( this.searchFields==null ) {
458
            return null;
459
        }
460
        int selectedRow = this.tblResults.getSelectedRow();
461
        if (selectedRow < 0) {
462
            return null;
463
        }
464
        try {
465
            List<Feature> features = ((SimpleFeaturesTableModel) this.tblResults.getModel()).getFeatures();
466
            Feature feature = features.get(selectedRow);
467
            
468
            ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
469
            FeatureType ftype = this.store.getDefaultFeatureType();
470
            for (FeatureAttributeDescriptor attrdesc : ftype.getPrimaryKey()) {
471
                builder.and(
472
                        builder.eq(
473
                                builder.column(attrdesc.getName()),
474
                                builder.constant(feature.get(attrdesc.getName()))
475
                        )
476
                );
477
            }
478
            Expression filter = ExpressionUtils.createExpression(builder.toString());
479
            return filter;
480
        } catch (Exception ex) {
481
            LOGGER.warn("Can't build search for the selected feature.", ex);
482
            return null;
483
        }
484
    }
485

    
486
    @Override
487
    public FeatureStore getStore() {
488
        return store;
489
    }
490
    
491
    @Override
492
    public ImageIcon loadImage(String imageName) {
493
        String name = FilenameUtils.getBaseName(imageName);
494
        IconTheme theme = ToolsSwingLocator.getIconThemeManager().getDefault();
495
        if (theme.exists(name)) {
496
            return theme.get(name);
497
        }
498
        URL url = this.getClass().getResource(name + ".png");
499
        if (url == null) {
500
            return null;
501
        }
502
        return new ImageIcon(url);
503
    }
504

    
505
    public static void selfRegister() {
506
        String[][] iconNames = new String[][]{
507
            new String[]{"dalswing", "featurestore-column"},
508
            new String[]{"dalswing", "featurestore-foreing-key"},
509
            new String[]{"dalswing", "featurestore-table"},
510
            new String[]{"dalswing", "search-action-showform"},
511
            new String[]{"dalswing", "search-action-select"},
512
            new String[]{"dalswing", "search-action-select-add"},
513
            new String[]{"dalswing", "search-action-select-filter"}
514
        };
515
        IconTheme theme = ToolsSwingLocator.getIconThemeManager().getCurrent();
516
        for (String[] icon : iconNames) {
517
            URL url = DefaultSearchPanel.class.getResource(icon[1] + ".png");
518
            theme.registerDefault("DALSwing", icon[0], icon[1], null, url);
519
        }
520

    
521
    }
522

    
523
    @Override
524
    public int getSelectedFeatureCount() {
525
        if( this.searchFields==null ) {
526
            return 0;
527
        }
528
        return this.tblResults.getSelectedRowCount();
529
    }
530
    
531
    @Override
532
    public JComponent getActionButton(String name) {
533
        ActionButtons actionButton = this.actions.get(name);
534
        if( actionButton==null ) {
535
            return null;
536
        }
537
        return actionButton.button;
538
    }
539

    
540
    @Override
541
    public void setShowActions(boolean showActions) {
542
        this.showActions = showActions;
543
    }
544
    
545
    @Override
546
    public boolean isShowActions() {
547
        return this.showActions;
548
    }
549
}