Statistics
| Revision:

gvsig-projects-pool / org.gvsig.topology / trunk / org.gvsig.topology / org.gvsig.topology.swing / org.gvsig.topology.swing.impl / src / main / java / org / gvsig / topology / swing / impl / DefaultJTopologyReport.java @ 726

History | View | Annotate | Download (22.7 KB)

1
package org.gvsig.topology.swing.impl;
2

    
3
import java.awt.BorderLayout;
4
import java.awt.Dimension;
5
import java.awt.event.ActionEvent;
6
import java.awt.event.ActionListener;
7
import java.awt.event.MouseAdapter;
8
import java.awt.event.MouseEvent;
9
import java.util.HashSet;
10
import java.util.List;
11
import java.util.Set;
12
import javax.swing.DefaultComboBoxModel;
13
import javax.swing.JComponent;
14
import javax.swing.JMenuItem;
15
import javax.swing.JPopupMenu;
16
import javax.swing.JTable;
17
import javax.swing.SwingUtilities;
18
import javax.swing.event.ChangeEvent;
19
import javax.swing.event.ChangeListener;
20
import javax.swing.event.ListSelectionEvent;
21
import javax.swing.event.ListSelectionListener;
22
import javax.swing.event.TableModelEvent;
23
import javax.swing.event.TableModelListener;
24
import javax.swing.table.TableModel;
25
import org.apache.commons.lang3.StringUtils;
26
import org.gvsig.expressionevaluator.ExpressionBuilder;
27
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
28
import org.gvsig.fmap.dal.feature.FeatureSelection;
29
import org.gvsig.fmap.geom.Geometry;
30
import org.gvsig.fmap.geom.primitive.Envelope;
31
import org.gvsig.tools.ToolsLocator;
32
import org.gvsig.tools.dynform.DynFormLocator;
33
import org.gvsig.tools.dynform.JDynForm;
34
import org.gvsig.tools.dynobject.DynObject;
35
import org.gvsig.tools.i18n.I18nManager;
36
import org.gvsig.tools.observer.Observable;
37
import org.gvsig.tools.observer.Observer;
38
import org.gvsig.tools.swing.api.ListElement;
39
import org.gvsig.tools.swing.api.ToolsSwingLocator;
40
import org.gvsig.tools.swing.api.ToolsSwingManager;
41
import org.gvsig.tools.swing.api.task.TaskStatusController;
42
import org.gvsig.tools.task.TaskStatus;
43
import org.gvsig.topology.lib.api.TopologyLocator;
44
import org.gvsig.topology.lib.api.TopologyPlan;
45
import org.gvsig.topology.lib.api.TopologyReport;
46
import org.gvsig.topology.lib.api.TopologyReportLine;
47
import org.gvsig.topology.lib.api.TopologyReportLineSet;
48
import org.gvsig.topology.lib.api.TopologyRule;
49
import org.gvsig.topology.lib.api.TopologyRuleAction;
50
import org.gvsig.topology.lib.api.TopologyRuleFactory;
51
import org.gvsig.topology.swing.api.JTopologyReport;
52
import org.gvsig.topology.swing.api.TopologySwingLocator;
53
import org.gvsig.topology.swing.api.TopologySwingServices;
54
import org.gvsig.topology.swing.api.TopologySwingServices.WorkingAreaChangedListener;
55
import org.slf4j.Logger;
56
import org.slf4j.LoggerFactory;
57

    
58
/**
59
 *
60
 * @author jjdelcerro
61
 */
62
@SuppressWarnings("UseSpecificCatch")
63
public class DefaultJTopologyReport
64
        extends DefaultJTopologyReportView
65
        implements JTopologyReport {
66

    
67
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultJTopologyReport.class);
68

    
69
    
70
    private class TopologyRuleActionParametersListener implements ActionListener {
71

    
72
        private final TopologyRule rule;
73
        private final TopologyReportLine line;
74
        private final TopologyRuleAction action;
75
        private final JDynForm form;
76

    
77
        public TopologyRuleActionParametersListener(
78
                TopologyRule rule,
79
                TopologyReportLine line,
80
                TopologyRuleAction action,
81
                JDynForm form
82
        ) {
83
            this.action = action;
84
            this.line = line;
85
            this.rule = rule;
86
            this.form = form;
87
        }
88

    
89
        @Override
90
        public void actionPerformed(ActionEvent e) {
91
            doExecuteRuleAction(rule, line, action, form);
92
        }
93
    }
94

    
95

    
96
    private class TopologyRuleActionListener implements ActionListener {
97

    
98
        private final TopologyRule rule;
99
        private final TopologyReportLine line;
100
        private final TopologyRuleAction action;
101

    
102
        public TopologyRuleActionListener(
103
                TopologyRule rule,
104
                TopologyReportLine line,
105
                TopologyRuleAction action
106
        ) {
107
            this.action = action;
108
            this.line = line;
109
            this.rule = rule;
110
        }
111

    
112
        @Override
113
        public void actionPerformed(ActionEvent e) {
114
            if ( this.action.hasParameters() ) {
115
                doShowActionParametersPanel(this.rule, this.line, this.action);
116
            } else {
117
                doExecuteRuleAction(rule, line, action, null);
118
            }
119
        }
120
    }
121
    
122
    private ReportTable linesModel;
123
    private final TopologySwingServices services;
124
    private TaskStatusController taskStatusController;
125
    private TopologyPlan plan;
126
    private WorkingAreaChangedListener workingAreaChangedListener;
127

    
128
    public DefaultJTopologyReport(TopologyPlan plan) {
129
        this.services = TopologySwingLocator.getTopologySwingManager().getDefaultServices();
130
        this.initComponents();
131
    }
132

    
133
    private void initComponents() {
134
        I18nManager i18n = ToolsLocator.getI18nManager();
135
        this.linesModel = new ReportTable();
136
        this.workingAreaChangedListener = new WorkingAreaChangedListener() {
137
            @Override
138
            public void workingAreaChanged(Envelope workingArea) {
139
                doUpdateFilter();
140
            }
141
        };
142
        this.tblErrors.setModel(this.linesModel);
143
        this.tblErrors.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
144
        this.btnZoom.addActionListener(new ActionListener() {
145
            @Override
146
            public void actionPerformed(ActionEvent e) {
147
                doZoom();
148
            }
149
        });
150
        this.btnCenter.addActionListener(new ActionListener() {
151
            @Override
152
            public void actionPerformed(ActionEvent e) {
153
                doCenter();
154
            }
155
        });
156
        this.btnRefresh.addActionListener(new ActionListener() {
157
            @Override
158
            public void actionPerformed(ActionEvent e) {
159
                doExecutePlan();
160
            }
161
        });
162
        this.tblErrors.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
163
            @Override
164
            public void valueChanged(ListSelectionEvent e) {
165
                doRowSelected();
166
            }
167
        });
168
        this.tblErrors.addMouseListener(new MouseAdapter() {
169
            @Override
170
            public void mouseClicked(MouseEvent e) {
171
                if( e.getButton()==MouseEvent.BUTTON1 && e.getClickCount()==2 ) {
172
                    doCenter();
173
                }
174
            }
175
        });
176
        
177
        this.btnActions.addActionListener(new ActionListener() {
178
            @Override
179
            public void actionPerformed(ActionEvent e) {
180
                doSelectAction();
181
            }
182
        });
183
        this.btnParametersCancel.addActionListener(new ActionListener() {
184
            @Override
185
            public void actionPerformed(ActionEvent e) {
186
                tabData.setEnabledAt(0, true);
187
                tabData.setEnabledAt(1, false);
188
                tabData.setSelectedIndex(0);
189
                pnlParameters.removeAll();
190
            }
191
        });
192
        this.btnShowErrors.addActionListener(new ActionListener() {
193
            @Override
194
            public void actionPerformed(ActionEvent e) {
195
                doUpdateFilter();
196
            }
197
        });
198
        this.btnShowExceptions.addActionListener(new ActionListener() {
199
            @Override
200
            public void actionPerformed(ActionEvent e) {
201
                doUpdateFilter();
202
            }
203
        });
204
        this.btnVisibleExtentOnly.addActionListener(new ActionListener() {
205
            @Override
206
            public void actionPerformed(ActionEvent e) {
207
                doUpdateFilter();
208
            }
209
        });
210
        DefaultComboBoxModel<ListElement<TopologyRuleFactory>> modelRules = new DefaultComboBoxModel<>();
211
        modelRules.addElement(new ListElement<>(i18n.getTranslation("_Any_rule"), (TopologyRuleFactory)null));
212
        List<TopologyRuleFactory> factories = TopologyLocator.getTopologyManager().getRuleFactories();
213
        for (TopologyRuleFactory factory : factories) {
214
            modelRules.addElement(new ListElement<>(factory.getName(), factory));
215
        }
216
        this.cboRules.setModel(modelRules);
217
        this.cboRules.addActionListener(new ActionListener() {
218
            @Override
219
            public void actionPerformed(ActionEvent e) {
220
                // Llama al invokeLater para poder debugguear
221
                SwingUtilities.invokeLater(new Runnable() {
222
                    @Override
223
                    public void run() {
224
                        doUpdateFilter();
225
                    }
226
                });
227
            }
228
        });
229
        this.taskStatusController = ToolsSwingLocator.getTaskStatusSwingManager().createTaskStatusController(
230
                null,
231
                this.lblTaskStatusTitle,
232
                this.lblTaskStatusMessage,
233
                this.pbTaskStatusProgress,
234
                this.btnTaskStatusCancel,
235
                null
236
        );
237
        this.translate();
238
        this.setPreferredSize(new Dimension(700, 200));
239

    
240
        this.btnShowErrors.setSelected(false);
241
        this.btnShowExceptions.setSelected(false);
242
        this.btnVisibleExtentOnly.setSelected(false);
243
        
244
        this.tabData.setEnabledAt(1, false);
245

    
246
    }
247

    
248
    private void translate() {
249
        ToolsSwingManager tsm = ToolsSwingLocator.getToolsSwingManager();
250
        tsm.translate(this.btnActions);
251
        tsm.translate(this.btnCenter);
252
        tsm.translate(this.btnRefresh);
253
        tsm.translate(this.btnShowErrors);
254
        tsm.translate(this.btnShowExceptions);
255
        tsm.translate(this.btnZoom);
256
        tsm.translate(this.btnVisibleExtentOnly);
257
        tsm.translate(this.btnParametersAccept);
258
        tsm.translate(this.btnParametersCancel);
259
        tsm.translate(this.lblShow);
260
        tsm.translate(this.tabData);
261
    }
262

    
263
    @Override
264
    public void put(TopologyPlan plan) {
265
        this.plan = plan;
266
        this.taskStatusController.bind(this.plan.getTaskStatus());
267
        this.plan.getTaskStatus().addObserver(new Observer() {
268
            @Override
269
            public void update(Observable o, Object o1) {
270
                doTaskStatusUpdated(o, o1);
271
            }
272
        });
273
        this.linesModel.setReport(plan.getReport());
274
    }
275

    
276
    @Override
277
    public JComponent asJComponent() {
278
        return this;
279
    }
280

    
281
    private void doUpdateFilter() {
282
        this.linesModel.setFilter(this.getFilter());
283
    }
284

    
285
    private String getFilter() {
286
        ExpressionBuilder builder = ExpressionEvaluatorLocator.getManager().createExpressionBuilder();
287
        TopologyRuleFactory ruleFactory = (TopologyRuleFactory) ListElement.getSelected(cboRules);
288
        if( ruleFactory != null ) {
289
            builder.setValue(
290
                builder.eq(
291
                    builder.column(TopologyReport.RULE_ID),
292
                    builder.constant(ruleFactory.getId())
293
                )
294
            );
295
        }
296
        if( this.btnShowErrors.isSelected() ) {
297
            if( btnShowExceptions.isSelected()) {
298
                builder.and(
299
                        builder.or(
300
                            builder.column(TopologyReport.IS_ERROR), 
301
                            builder.column(TopologyReport.IS_EXCEPTION)
302
                        )
303
                );
304
            } else {
305
                builder.and(
306
                    builder.column(TopologyReport.IS_ERROR)
307
                );
308
            }
309
        } else if( btnShowExceptions.isSelected()) {
310
            builder.and(
311
                builder.column(TopologyReport.IS_EXCEPTION)
312
            );
313
        }
314
        if( this.btnVisibleExtentOnly.isSelected() ) {
315
            Envelope workingArea = this.services.getWorkingArea();
316
            if( workingArea!=null ) {
317
                builder.and(
318
                        builder.ST_Intersects(
319
                                builder.column(TopologyReport.GEOMETRY), 
320
                                builder.geometry(workingArea.getGeometry())
321
                        )
322
                );
323
            }
324
            this.services.addWorkingAreaChangedListener(this.workingAreaChangedListener);
325
        } else {
326
            this.services.removeWorkingAreaChangedListener(this.workingAreaChangedListener);
327
        }
328
        if( builder.getValue()==null ) {
329
            return null;
330
        }
331
        return builder.toString();
332
    }
333
    
334
    private void doExecutePlan() {
335
        Thread th = new Thread(new Runnable() {
336
            @Override
337
            public void run() {
338
                plan.execute();
339
            }
340
        }, "TopologyPlan-" + plan.getName());
341
        th.start();
342
    }
343

    
344
    private void doTaskStatusUpdated(final Observable observable, final Object notification) {
345
        if (observable != null && !(observable instanceof TaskStatus)) {
346
            return;
347
        }
348
        if (!SwingUtilities.isEventDispatchThread()) {
349
            SwingUtilities.invokeLater(new Runnable() {
350
                public void run() {
351
                    doTaskStatusUpdated(observable, notification);
352
                }
353
            });
354
            return;
355
        }
356
        TaskStatus taskStatus = (TaskStatus) observable;
357
        if (taskStatus==null || !taskStatus.isRunning()) {
358
            this.lblTaskStatusTitle.setVisible(false);
359
            this.lblTaskStatusMessage.setVisible(false);
360
            this.pbTaskStatusProgress.setVisible(false);
361
            this.btnTaskStatusCancel.setVisible(false);
362
            this.btnRefresh.setEnabled(true);
363
            I18nManager i18n = ToolsLocator.getI18nManager();
364
            message(i18n.getTranslation("_Errors")+": "+this.linesModel.getRowCount());
365
            return;
366
        }
367
        if (!this.pbTaskStatusProgress.isVisible()) {
368
            this.lblTaskStatusTitle.setVisible(true);
369
            this.lblTaskStatusMessage.setVisible(true);
370
            this.pbTaskStatusProgress.setVisible(true);
371
            this.btnTaskStatusCancel.setVisible(true);
372
            this.btnRefresh.setEnabled(false);
373
        }
374
    }
375

    
376
    private void message(String msg) {
377
        this.lblTaskStatusTitle.setText(msg);
378
        this.lblTaskStatusTitle.setVisible(true);
379
    }
380
    
381
    private void doSelectAction() {
382
        int n = this.tblErrors.getSelectedRow();
383
        if (n < 0) {
384
            return;
385
        }
386
        TopologyReportLine line = this.linesModel.getLine(n);
387
        TopologyRule rule = line.getRule();
388
        List<TopologyRuleAction> actions = rule.getActions();
389
        if (actions == null || actions.isEmpty()) {
390
            return;
391
        }
392
        JPopupMenu menu = new JPopupMenu();
393
        for (TopologyRuleAction action : actions) {
394
            JMenuItem item;
395
            if( action.hasParameters() ) {
396
                item = new JMenuItem(action.getName()+"..."); 
397
            } else {
398
                item = new JMenuItem(action.getName()); 
399
            }
400
            item.addActionListener(new TopologyRuleActionListener(rule, line, action));
401
            menu.add(item);
402
        }
403
        menu.show(this.btnActions, 0, this.btnActions.getHeight());
404
    }
405

    
406
    private void doExecuteRuleAction(
407
            TopologyRule rule,
408
            TopologyReportLine line,
409
            TopologyRuleAction action,
410
            JDynForm form
411
    ) {
412
        DynObject parameters = null;
413
        if( form!=null ) {
414
            parameters = action.createParameters();
415
            if( parameters!=null ) {
416
                form.getValues(parameters);
417
            }
418
        }
419
        action.execute(rule, line, parameters);
420
        this.tabData.setEnabledAt(0, true);
421
        this.tabData.setEnabledAt(1, false);
422
        this.tabData.setSelectedIndex(0);
423
        this.pnlParameters.removeAll();
424
        this.services.refreshView();
425
    }
426

    
427
    private void doShowActionParametersPanel(
428
            TopologyRule rule,
429
            TopologyReportLine line,
430
            TopologyRuleAction action
431
    ) {
432
        I18nManager i18n = ToolsLocator.getI18nManager();
433
        this.tabData.setEnabledAt(0, false);
434
        this.tabData.setEnabledAt(1, true);
435
        this.tabData.setSelectedIndex(1);
436

    
437
        try {
438
            JDynForm form = null;
439
            this.lblActionTitle.setText(
440
                    "<html>" +
441
                    i18n.getTranslation("_Rule") + ": <b>" +
442
                    rule.getName() + "</b>, " +
443
                    i18n.getTranslation("_Action") + ": <b>" +
444
                    action.getName() + "</b></html>"
445
            );
446
            this.lblActionDescription.setText("<html>"+action.getShortDescription()+"</html>");
447
            DynObject parameters = action.createParameters();
448
            if( parameters!=null ) {
449
                form = DynFormLocator.getDynFormManager().createJDynForm(parameters);
450
                if( form!=null ) {
451
                    this.pnlParameters.setLayout(new BorderLayout());
452
                    this.pnlParameters.removeAll();
453
                    this.pnlParameters.add(form.asJComponent(), BorderLayout.CENTER);
454
                    this.pnlParameters.revalidate();
455
                    this.pnlParameters.repaint();
456
                }
457
            }
458
            this.btnParametersAccept.addActionListener(
459
                new TopologyRuleActionParametersListener(rule, line, action, form)
460
            );
461
        } catch (Exception ex) {
462
            LOGGER.warn("Can't show action parameters panel.",ex);
463
        }
464
    }
465

    
466
    private void doZoom() {
467
        int n = this.tblErrors.getSelectedRow();
468
        if (n < 0) {
469
            return;
470
        }
471
        TopologyReportLine line = this.linesModel.getLine(n);
472
        Geometry geom = line.getGeometry();
473
        this.services.zoomTo(geom.getEnvelope());
474
    }
475

    
476
    private void doCenter() {
477
        try {
478
            int n = this.tblErrors.getSelectedRow();
479
            if (n < 0) {
480
                return;
481
            }
482
            TopologyReportLine line = this.linesModel.getLine(n);
483
            Geometry geom = line.getGeometry();
484
            this.services.centerTo(geom.centroid());
485
        } catch (Exception ex) {
486
            LOGGER.warn("Can't center topology error", ex);
487
        }
488
    }
489

    
490
    private void doRowSelected() {
491
        try {
492
            int n = this.tblErrors.getSelectedRow();
493
            if (n < 0) {
494
                return;
495
            }
496
            TopologyReportLine line = this.linesModel.getLine(n);
497
            if (line.getFeature1() == null) {
498
                return;
499
            }
500
            FeatureSelection selection = line.getDataSet1().getStore().getFeatureSelection();
501
            selection.deselectAll();
502
            selection.select(line.getFeature1());
503
        } catch (Exception ex) {
504
            LOGGER.warn("Can't select topology error", ex);
505
        }
506
    }
507

    
508
    private static class ReportTable implements TableModel {
509

    
510
        private TopologyReport report;
511
        private TopologyReportLineSet lines;
512
        private final String[] columnNames;
513
        private final Class[] columnClasses;
514
        private final Set<TableModelListener> tableListeners;
515
        private final ChangeListener reportListener;
516
        private String lastFilter;
517

    
518
        public ReportTable() {
519
            I18nManager i18n = ToolsLocator.getI18nManager();
520
            this.report = null;
521
            this.lines = null;
522
            this.tableListeners = new HashSet<>();
523
            this.columnNames = new String[]{
524
                i18n.getTranslation("_Rule"),
525
                i18n.getTranslation("_Dataset1"),
526
                i18n.getTranslation("_Dataset2"),
527
                i18n.getTranslation("_Exception"),
528
                i18n.getTranslation("_Description")
529
            };
530
            this.columnClasses = new Class[]{
531
                String.class,
532
                String.class,
533
                String.class,
534
                Boolean.class,
535
                String.class
536
            };
537
            this.reportListener = new ChangeListener() {
538
                @Override
539
                public void stateChanged(final ChangeEvent e) {
540
                    if( !SwingUtilities.isEventDispatchThread() ) {
541
                        SwingUtilities.invokeLater(new Runnable() {
542
                            @Override
543
                            public void run() {
544
                                stateChanged(e);
545
                            }
546
                        });
547
                        return;
548
                    }
549
                    fireTableChanged();
550
                }
551
            };
552
        }
553

    
554
        public void setReport(TopologyReport report) {
555
            if (this.report != null) {
556
                this.report.removeChangeListener(this.reportListener);
557
            }
558
            this.report = report;
559
            this.lines = this.report;
560
            this.lines.addChangeListener(this.reportListener);
561
        }
562

    
563
        public void setFilter(String filter) {
564
            if( StringUtils.equals(filter, this.lastFilter) ) {
565
                return;
566
            }
567
            this.lines = this.report.getLineSet(filter);
568
            this.lines.addChangeListener(this.reportListener);
569
            this.lastFilter = filter;
570
            this.fireTableChanged();
571
        }
572
        
573
        public TopologyReport getReport() {
574
            return this.report;
575
        }
576

    
577
        @Override
578
        public int getRowCount() {
579
            if (this.lines == null) {
580
                return 0;
581
            }
582
            return this.lines.size();
583
        }
584

    
585
        @Override
586
        public int getColumnCount() {
587
            return 5;
588
        }
589

    
590
        @Override
591
        public String getColumnName(int columnIndex) {
592
            return this.columnNames[columnIndex];
593
        }
594

    
595
        @Override
596
        public Class<?> getColumnClass(int columnIndex) {
597
            return this.columnClasses[columnIndex];
598
        }
599

    
600
        @Override
601
        public boolean isCellEditable(int rowIndex, int columnIndex) {
602
            return false;
603
        }
604

    
605
        @Override
606
        public Object getValueAt(int rowIndex, int columnIndex) {
607
            if (this.lines == null) {
608
                return "";
609
            }
610
            TopologyReportLine line = this.lines.get(rowIndex);
611
            switch (columnIndex) {
612
                case 0:
613
                    return line.getRule().getName();
614
                case 1:
615
                    return line.getDataSet1().getName();
616
                case 2:
617
                    if (line.getDataSet2() == null) {
618
                        return "";
619
                    }
620
                    return line.getDataSet2().getName();
621
                case 3:
622
                    return line.isException();
623
                case 4:
624
                    return line.getDescription();
625
                default:
626
                    return "???";
627
            }
628
        }
629

    
630
        @Override
631
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
632
        }
633

    
634
        @Override
635
        public void addTableModelListener(TableModelListener l) {
636
            this.tableListeners.add(l);
637
        }
638

    
639
        @Override
640
        public void removeTableModelListener(TableModelListener l) {
641
            this.tableListeners.remove(l);
642
        }
643

    
644
        private void fireTableChanged() {
645
            for (TableModelListener tableListener : this.tableListeners) {
646
                tableListener.tableChanged(new TableModelEvent(this));
647
            }
648
        }
649

    
650
        public TopologyReportLine getLine(int lineNum) {
651
            return this.lines.get(lineNum);
652
        }
653

    
654
    }
655
}