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

History | View | Annotate | Download (29.5 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.net.URL;
10
import java.util.ArrayList;
11
import java.util.HashSet;
12
import java.util.List;
13
import java.util.Set;
14
import java.util.logging.Level;
15
import javax.swing.DefaultComboBoxModel;
16
import javax.swing.DefaultListSelectionModel;
17
import javax.swing.ImageIcon;
18
import javax.swing.JComponent;
19
import javax.swing.JMenuItem;
20
import javax.swing.JPopupMenu;
21
import javax.swing.JTable;
22
import javax.swing.ListSelectionModel;
23
import javax.swing.SwingUtilities;
24
import javax.swing.event.ChangeEvent;
25
import javax.swing.event.ChangeListener;
26
import javax.swing.event.ListSelectionEvent;
27
import javax.swing.event.ListSelectionListener;
28
import javax.swing.event.TableModelEvent;
29
import javax.swing.event.TableModelListener;
30
import javax.swing.table.TableModel;
31
import org.apache.commons.io.FilenameUtils;
32
import org.apache.commons.lang3.StringUtils;
33
import org.gvsig.expressionevaluator.ExpressionBuilder;
34
import org.gvsig.expressionevaluator.ExpressionUtils;
35
import org.gvsig.expressionevaluator.GeometryExpressionBuilder;
36
import org.gvsig.expressionevaluator.GeometryExpressionUtils;
37
import org.gvsig.featureform.swing.CreateJFeatureFormException;
38
import org.gvsig.fmap.dal.DataStore;
39
import org.gvsig.fmap.dal.exception.DataException;
40
import org.gvsig.fmap.dal.feature.FeatureSelection;
41
import org.gvsig.fmap.dal.feature.FeatureStore;
42
import org.gvsig.fmap.geom.Geometry;
43
import org.gvsig.fmap.geom.primitive.Envelope;
44
import org.gvsig.tools.ToolsLocator;
45
import org.gvsig.tools.dynform.DynFormLocator;
46
import org.gvsig.tools.dynform.JDynForm;
47
import org.gvsig.tools.dynobject.DynObject;
48
import org.gvsig.tools.i18n.I18nManager;
49
import org.gvsig.tools.observer.Observable;
50
import org.gvsig.tools.observer.Observer;
51
import org.gvsig.tools.service.ServiceException;
52
import org.gvsig.tools.swing.api.ListElement;
53
import org.gvsig.tools.swing.api.ToolsSwingLocator;
54
import org.gvsig.tools.swing.api.ToolsSwingManager;
55
import org.gvsig.tools.swing.api.task.TaskStatusController;
56
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
57
import org.gvsig.tools.swing.icontheme.IconTheme;
58
import org.gvsig.tools.task.TaskStatus;
59
import org.gvsig.topology.lib.api.TopologyLocator;
60
import org.gvsig.topology.lib.api.TopologyPlan;
61
import org.gvsig.topology.lib.api.TopologyReport;
62
import org.gvsig.topology.lib.api.TopologyReportLine;
63
import org.gvsig.topology.lib.api.TopologyReportLineSet;
64
import org.gvsig.topology.lib.api.TopologyRule;
65
import org.gvsig.topology.lib.api.TopologyRuleAction;
66
import org.gvsig.topology.lib.api.TopologyRuleFactory;
67
import org.gvsig.topology.swing.api.JTopologyReport;
68
import org.gvsig.topology.swing.api.TopologySwingLocator;
69
import org.gvsig.topology.swing.api.TopologySwingServices;
70
import org.gvsig.topology.swing.api.TopologySwingServices.WorkingAreaChangedListener;
71
import org.slf4j.Logger;
72
import org.slf4j.LoggerFactory;
73

    
74
import org.gvsig.featureform.swing.JFeaturesForm;
75
import org.gvsig.fmap.dal.feature.Feature;
76
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
77
import org.gvsig.fmap.dal.feature.FeatureQuery;
78
import org.gvsig.fmap.dal.feature.FeatureReference;
79
import org.gvsig.fmap.dal.feature.FeatureType;
80
import org.gvsig.fmap.dal.swing.DALSwingLocator;
81
import org.gvsig.fmap.dal.swing.DataSwingManager;
82

    
83
/**
84
 *
85
 * @author jjdelcerro
86
 */
87
@SuppressWarnings("UseSpecificCatch")
88
public class DefaultJTopologyReport
89
        extends DefaultJTopologyReportView
90
        implements JTopologyReport {
91

    
92
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultJTopologyReport.class);
93
    private ListSelectionModel selection;
94

    
95
    private class TopologyRuleActionParametersListener implements ActionListener {
96

    
97
        private final TopologyRule rule;
98
        private final List<TopologyReportLine> lines;
99
        private final TopologyRuleAction action;
100
        private final JDynForm form;
101

    
102
        public TopologyRuleActionParametersListener(
103
                TopologyRule rule,
104
                List<TopologyReportLine> lines,
105
                TopologyRuleAction action,
106
                JDynForm form
107
        ) {
108
            this.action = action;
109
            this.lines = lines;
110
            this.rule = rule;
111
            this.form = form;
112
        }
113

    
114
        @Override
115
        public void actionPerformed(ActionEvent e) {
116
            doExecuteRuleAction(rule, lines, action, form);
117
        }
118
    }
119

    
120
    private class TopologyRuleActionListener implements ActionListener {
121

    
122
        private final TopologyRule rule;
123
        private final List<TopologyReportLine> lines;
124
        private final TopologyRuleAction action;
125

    
126
        public TopologyRuleActionListener(
127
                TopologyRule rule,
128
                List<TopologyReportLine> lines,
129
                TopologyRuleAction action
130
        ) {
131
            this.action = action;
132
            this.lines = lines;
133
            this.rule = rule;
134
        }
135

    
136
        @Override
137
        public void actionPerformed(ActionEvent e) {
138
            if (this.action.hasParameters()) {
139
                doShowActionParametersPanel(this.rule, this.lines, this.action);
140
            } else {
141
                doExecuteRuleAction(rule, lines, action, null);
142
            }
143
        }
144
    }
145

    
146
    private ReportTable linesModel;
147
    private final TopologySwingServices services;
148
    private TaskStatusController taskStatusController;
149
    private TopologyPlan plan;
150
    private WorkingAreaChangedListener workingAreaChangedListener;
151

    
152
    public DefaultJTopologyReport(TopologyPlan plan) {
153
        this.services = TopologySwingLocator.getTopologySwingManager().getDefaultServices();
154
        this.initComponents();
155
    }
156

    
157
    private void initComponents() {
158
        I18nManager i18n = ToolsLocator.getI18nManager();
159
        this.selection = this.tblErrors.getSelectionModel();
160
        this.linesModel = new ReportTable();
161

    
162
        this.workingAreaChangedListener = new WorkingAreaChangedListener() {
163
            @Override
164
            public void workingAreaChanged(Envelope workingArea) {
165
                doUpdateFilter();
166
            }
167
        };
168
        this.tblErrors.setModel(this.linesModel);
169
        this.tblErrors.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
170

    
171
        this.btnZoomGeometry.addActionListener(new ActionListener() {
172
            @Override
173
            public void actionPerformed(ActionEvent e) {
174
                doZoomGeometry();
175
            }
176
        });
177
        this.btnZoomError.addActionListener(new ActionListener() {
178
            @Override
179
            public void actionPerformed(ActionEvent e) {
180
                doZoomError();
181
            }
182
        });
183
        this.btnCenterGeometry.addActionListener(new ActionListener() {
184
            @Override
185
            public void actionPerformed(ActionEvent e) {
186
                doCenterGeometry();
187
            }
188
        });
189
        this.btnCenterError.addActionListener(new ActionListener() {
190
            @Override
191
            public void actionPerformed(ActionEvent e) {
192
                doCenterError();
193
            }
194
        });
195
        this.btnRefresh.addActionListener(new ActionListener() {
196
            @Override
197
            public void actionPerformed(ActionEvent e) {
198
                doExecutePlan();
199
            }
200
        });
201
        this.tblErrors.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
202
            @Override
203
            public void valueChanged(ListSelectionEvent e) {
204
                doRowSelected();
205
            }
206
        });
207
        this.tblErrors.addMouseListener(new MouseAdapter() {
208
            @Override
209
            public void mouseClicked(MouseEvent e) {
210
                if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
211
                    doCenterError();
212
                }
213
            }
214
        });
215

    
216
        this.btnActions.addActionListener(new ActionListener() {
217
            @Override
218
            public void actionPerformed(ActionEvent e) {
219
                doSelectAction();
220
            }
221
        });
222
        this.btnParametersCancel.addActionListener(new ActionListener() {
223
            @Override
224
            public void actionPerformed(ActionEvent e) {
225
                tabData.setEnabledAt(0, true);
226
                tabData.setEnabledAt(1, false);
227
                tabData.setSelectedIndex(0);
228
                pnlParameters.removeAll();
229
            }
230
        });
231
        this.btnShowErrors.addActionListener(new ActionListener() {
232
            @Override
233
            public void actionPerformed(ActionEvent e) {
234
                doUpdateFilter();
235
            }
236
        });
237
        this.btnShowExceptions.addActionListener(new ActionListener() {
238
            @Override
239
            public void actionPerformed(ActionEvent e) {
240
                doUpdateFilter();
241
            }
242
        });
243
        this.btnVisibleExtentOnly.addActionListener(new ActionListener() {
244
            @Override
245
            public void actionPerformed(ActionEvent e) {
246
                doUpdateFilter();
247
            }
248
        });
249
        this.btnShowForm.addActionListener(new ActionListener() {
250
            @Override
251
            public void actionPerformed(ActionEvent e) {
252
                services.setShowFormWhenEdit(btnShowForm.isSelected());
253
            }
254
        });
255
        this.btnEraseErrorMarks.addActionListener(new ActionListener() {
256
            @Override
257
            public void actionPerformed(ActionEvent e) {
258
                services.addError(null);
259
            }
260
        });
261
        DefaultComboBoxModel<ListElement<TopologyRuleFactory>> modelRules = new DefaultComboBoxModel<>();
262
        modelRules.addElement(new ListElement<>(i18n.getTranslation("_Any_rule"), (TopologyRuleFactory) null));
263
        List<TopologyRuleFactory> factories = TopologyLocator.getTopologyManager().getRuleFactories();
264
        for (TopologyRuleFactory factory : factories) {
265
            modelRules.addElement(new ListElement<>(factory.getName(), factory));
266
        }
267
        this.cboRules.setModel(modelRules);
268
        this.cboRules.addActionListener(new ActionListener() {
269
            @Override
270
            public void actionPerformed(ActionEvent e) {
271
                // Llama al invokeLater para poder debugguear
272
                SwingUtilities.invokeLater(new Runnable() {
273
                    @Override
274
                    public void run() {
275
                        doUpdateFilter();
276
                    }
277
                });
278
            }
279
        });
280
        
281
        this.btnShowFormGsOC2020.addActionListener(new ActionListener() {
282
            @Override
283
            public void actionPerformed(ActionEvent e) {
284
                showErrorForm();
285
            }
286
        });       
287
        
288
        this.taskStatusController = ToolsSwingLocator.getTaskStatusSwingManager().createTaskStatusController(
289
                null,
290
                this.lblTaskStatusTitle,
291
                this.lblTaskStatusMessage,
292
                this.pbTaskStatusProgress,
293
                this.btnTaskStatusCancel,
294
                null
295
        );
296
        this.translate();
297
        this.setPreferredSize(new Dimension(700, 200));
298

    
299
        this.btnShowErrors.setSelected(false);
300
        this.btnShowExceptions.setSelected(false);
301
        this.btnVisibleExtentOnly.setSelected(false);
302

    
303
        this.tabData.setEnabledAt(1, false);
304

    
305
    }
306

    
307
    @Override
308
    public ImageIcon loadImage(String imageName) {
309
        String name = FilenameUtils.getBaseName(imageName);
310
        IconTheme theme = ToolsSwingLocator.getIconThemeManager().getDefault();
311
        if (theme.exists(name)) {
312
            return theme.get(name);
313
        }
314
        URL url = this.getClass().getResource("/" + imageName);
315
        if (url == null) {
316
            return null;
317
        }
318
        return new ImageIcon(url);
319
    }
320

    
321
    private void translate() {
322
        ToolsSwingManager tsm = ToolsSwingLocator.getToolsSwingManager();
323
        tsm.translate(this.btnActions);
324
        tsm.translate(this.btnCenterError);
325
        tsm.translate(this.btnCenterGeometry);
326
        tsm.translate(this.btnRefresh);
327
        tsm.translate(this.btnShowErrors);
328
        tsm.translate(this.btnShowExceptions);
329
        tsm.translate(this.btnZoomError);
330
        tsm.translate(this.btnZoomGeometry);
331
        tsm.translate(this.btnEraseErrorMarks);
332
        tsm.translate(this.btnVisibleExtentOnly);
333
        tsm.translate(this.btnParametersAccept);
334
        tsm.translate(this.btnParametersCancel);
335
        tsm.translate(this.btnShowForm);
336
        tsm.translate(this.lblShow);
337
        tsm.translate(this.tabData);
338
    }
339

    
340
    @Override
341
    public void put(TopologyPlan plan) {
342
        this.plan = plan;
343
        this.taskStatusController.bind(this.plan.getTaskStatus());
344
        this.plan.getTaskStatus().addObserver(new Observer() {
345
            @Override
346
            public void update(Observable o, Object o1) {
347
                doTaskStatusUpdated(o, o1);
348
            }
349
        });
350
        this.linesModel.setReport(plan.getReport());
351
    }
352

    
353
    @Override
354
    public JComponent asJComponent() {
355
        return this;
356
    }
357

    
358
    private void doUpdateFilter() {
359
        this.linesModel.setFilter(this.getFilter());
360
    }
361

    
362
    private String getFilter() {
363
        GeometryExpressionBuilder builder = GeometryExpressionUtils.createExpressionBuilder();
364
        TopologyRuleFactory ruleFactory = (TopologyRuleFactory) ListElement.getSelected(cboRules);
365
        if (ruleFactory != null) {
366
            builder.set(
367
                    builder.eq(
368
                            builder.column(TopologyReport.RULE_ID),
369
                            builder.constant(ruleFactory.getId())
370
                    )
371
            );
372
        }
373
        if (this.btnShowErrors.isSelected()) {
374
            if (btnShowExceptions.isSelected()) {
375
                builder.and(
376
                        builder.or(
377
                                builder.column(TopologyReport.IS_ERROR),
378
                                builder.column(TopologyReport.IS_EXCEPTION)
379
                        )
380
                );
381
            } else {
382
                builder.and(
383
                        builder.column(TopologyReport.IS_ERROR)
384
                );
385
            }
386
        } else if (btnShowExceptions.isSelected()) {
387
            builder.and(
388
                    builder.column(TopologyReport.IS_EXCEPTION)
389
            );
390
        }
391
        if (this.btnVisibleExtentOnly.isSelected()) {
392
            Envelope workingArea = this.services.getWorkingArea();
393
            if (workingArea != null) {
394
                builder.and(
395
                        builder.ST_Intersects(
396
                                builder.column(TopologyReport.GEOMETRY),
397
                                builder.geometry(workingArea.getGeometry())
398
                        )
399
                );
400
            }
401
            this.services.addWorkingAreaChangedListener(this.workingAreaChangedListener);
402
        } else {
403
            this.services.removeWorkingAreaChangedListener(this.workingAreaChangedListener);
404
        }
405
        if (builder.value() == null) {
406
            return null;
407
        }
408
        return builder.toString();
409
    }
410

    
411
    private void doExecutePlan() {
412
        Thread th = new Thread(new Runnable() {
413
            @Override
414
            public void run() {
415
                plan.execute();
416
            }
417
        }, "TopologyPlan-" + plan.getName());
418
        th.start();
419
    }
420

    
421
    private void doTaskStatusUpdated(final Observable observable, final Object notification) {
422
        if (observable != null && !(observable instanceof TaskStatus)) {
423
            return;
424
        }
425
        if (!SwingUtilities.isEventDispatchThread()) {
426
            SwingUtilities.invokeLater(new Runnable() {
427
                public void run() {
428
                    doTaskStatusUpdated(observable, notification);
429
                }
430
            });
431
            return;
432
        }
433
        TaskStatus taskStatus = (TaskStatus) observable;
434
        if (taskStatus == null || !taskStatus.isRunning()) {
435
            this.lblTaskStatusTitle.setVisible(false);
436
            this.lblTaskStatusMessage.setVisible(false);
437
            this.pbTaskStatusProgress.setVisible(false);
438
            this.btnTaskStatusCancel.setVisible(false);
439
            this.btnRefresh.setEnabled(true);
440
            I18nManager i18n = ToolsLocator.getI18nManager();
441
            message(i18n.getTranslation("_Errors") + ": " + this.linesModel.getRowCount());
442
            return;
443
        }
444
        if (!this.pbTaskStatusProgress.isVisible()) {
445
            this.lblTaskStatusTitle.setVisible(true);
446
            this.lblTaskStatusMessage.setVisible(true);
447
            this.pbTaskStatusProgress.setVisible(true);
448
            this.btnTaskStatusCancel.setVisible(true);
449
            this.btnRefresh.setEnabled(false);
450
        }
451
    }
452

    
453
    private void message(String msg) {
454
        this.lblTaskStatusTitle.setText(msg);
455
        this.lblTaskStatusTitle.setVisible(true);
456
    }
457

    
458
    private void doSelectAction() {
459
        int n = this.tblErrors.getSelectedRow();
460
        if (n < 0) {
461
            return;
462
        }
463
        int[] selectedRows = this.tblErrors.getSelectedRows();
464
        TopologyRule rule = this.linesModel.getLine(selectedRows[0]).getRule();
465
        List<TopologyRuleAction> actions = rule.getActions();
466
        if (actions == null || actions.isEmpty()) {
467
            return;
468
        }
469
        List<TopologyReportLine> lines = new ArrayList<>();
470
        for (int selectedRow : selectedRows) {
471
            TopologyReportLine line = this.linesModel.getLine(selectedRow);
472
            if (line.getRule() == rule) {
473
                lines.add(line);
474
            }
475
        }
476
        JPopupMenu menu = new JPopupMenu();
477
        for (TopologyRuleAction action : actions) {
478
            JMenuItem item;
479
            if (action.hasParameters()) {
480
                item = new JMenuItem(action.getName() + "...");
481
            } else {
482
                item = new JMenuItem(action.getName());
483
            }
484
            item.addActionListener(new TopologyRuleActionListener(rule, lines, action));
485
            if (lines.size() > 1 && action.hasParameters()) {
486
                item.setEnabled(false);
487
            }
488
            menu.add(item);
489
        }
490
        menu.show(this.btnActions, 0, this.btnActions.getHeight());
491
    }
492

    
493
    private void doExecuteRuleAction(
494
            TopologyRule rule,
495
            List<TopologyReportLine> lines,
496
            TopologyRuleAction action,
497
            JDynForm form
498
    ) {
499
        DynObject parameters = null;
500
        if (form != null) {
501
            parameters = action.createParameters();
502
            if (parameters != null) {
503
                form.getValues(parameters);
504
            }
505
        }
506
        for (TopologyReportLine line : lines) {
507
            action.execute(rule, line, parameters);
508
        }
509
        this.tabData.setEnabledAt(0, true);
510
        this.tabData.setEnabledAt(1, false);
511
        this.tabData.setSelectedIndex(0);
512
        this.pnlParameters.removeAll();
513
        this.services.addError(null);
514
    }
515

    
516
    private void doShowActionParametersPanel(
517
            TopologyRule rule,
518
            List<TopologyReportLine> lines,
519
            TopologyRuleAction action
520
    ) {
521
        I18nManager i18n = ToolsLocator.getI18nManager();
522
        this.tabData.setEnabledAt(0, false);
523
        this.tabData.setEnabledAt(1, true);
524
        this.tabData.setSelectedIndex(1);
525

    
526
        try {
527
            JDynForm form = null;
528
            this.lblActionTitle.setText(
529
                    "<html>"
530
                    + i18n.getTranslation("_Rule") + ": <b>"
531
                    + rule.getName() + "</b>, "
532
                    + i18n.getTranslation("_Action") + ": <b>"
533
                    + action.getName() + "</b></html>"
534
            );
535
            this.lblActionDescription.setText("<html>" + action.getShortDescription() + "</html>");
536
            DynObject parameters = action.createParameters();
537
            if (parameters != null) {
538
                form = DynFormLocator.getDynFormManager().createJDynForm(parameters);
539
                if (form != null) {
540
                    this.pnlParameters.setLayout(new BorderLayout());
541
                    this.pnlParameters.removeAll();
542
                    this.pnlParameters.add(form.asJComponent(), BorderLayout.CENTER);
543
                    this.pnlParameters.revalidate();
544
                    this.pnlParameters.repaint();
545
                }
546
            }
547
            this.btnParametersAccept.addActionListener(
548
                    new TopologyRuleActionParametersListener(rule, lines, action, form)
549
            );
550
        } catch (Exception ex) {
551
            LOGGER.warn("Can't show action parameters panel.", ex);
552
        }
553
    }
554

    
555
    private void doZoomGeometry() {
556
        int n = this.tblErrors.getSelectedRow();
557
        if (n < 0) {
558
            return;
559
        }
560
        TopologyReportLine line = this.linesModel.getLine(n);
561
        Geometry geom = line.getGeometry();
562
        this.services.zoomTo(geom.getEnvelope());
563
    }
564

    
565
    private void doZoomError() {
566
        int n = this.tblErrors.getSelectedRow();
567
        if (n < 0) {
568
            return;
569
        }
570
        TopologyReportLine line = this.linesModel.getLine(n);
571
        Geometry geom = line.getError();
572
        if (geom == null) {
573
            geom = line.getGeometry();
574
            services.addError(null);
575
        } else {
576
            services.addError(geom);
577
        }
578
        this.services.zoomTo(geom.getEnvelope());
579
    }
580

    
581
    private void doCenterGeometry() {
582
        try {
583
            int n = this.tblErrors.getSelectedRow();
584
            if (n < 0) {
585
                return;
586
            }
587
            TopologyReportLine line = this.linesModel.getLine(n);
588
            Geometry geom = line.getGeometry();
589
            this.services.centerTo(geom.centroid());
590
        } catch (Exception ex) {
591
            LOGGER.warn("Can't center topology error", ex);
592
        }
593
    }
594

    
595
    private void doCenterError() {
596
        try {
597
            int n = this.tblErrors.getSelectedRow();
598
            if (n < 0) {
599
                return;
600
            }
601
            TopologyReportLine line = this.linesModel.getLine(n);
602
            Geometry geom = line.getError();
603
            if (geom == null) {
604
                geom = line.getGeometry();
605
                services.addError(null);
606
            } else {
607
                services.addError(geom);
608
            }
609
            this.services.centerTo(geom.centroid());
610
        } catch (Exception ex) {
611
            LOGGER.warn("Can't center topology error", ex);
612
        }
613
    }
614

    
615
    private void doRowSelected() {
616
        try {
617
            int n = this.tblErrors.getSelectedRow();
618
            if (n < 0) {
619
                return;
620
            }
621
            TopologyReportLine line = this.linesModel.getLine(n);
622
            if (line.getFeature1() == null) {
623
                return;
624
            }
625
            this.services.addError(null);
626
            FeatureSelection selection = line.getDataSet1().getFeatureStore().getFeatureSelection();
627
            selection.deselectAll();
628
            selection.select(line.getFeature1());
629
        } catch (Exception ex) {
630
            LOGGER.warn("Can't select topology error", ex);
631
        }
632
    }
633

    
634
    private class ReportTable implements TableModel {
635

    
636
        private TopologyReport report;
637
        private TopologyReportLineSet lines;
638
        private final String[] columnNames;
639
        private final Class[] columnClasses;
640
        private final Set<TableModelListener> tableListeners;
641
        private final ChangeListener reportListener;
642
        private String lastFilter;
643

    
644
        public ReportTable() {
645
            I18nManager i18n = ToolsLocator.getI18nManager();
646
            this.report = null;
647
            this.lines = null;
648
            this.tableListeners = new HashSet<>();
649
            this.columnNames = new String[]{
650
                i18n.getTranslation("_Rule"),
651
                i18n.getTranslation("_Dataset1"),
652
                i18n.getTranslation("_Dataset2"),
653
                i18n.getTranslation("_Exception"),
654
                i18n.getTranslation("_Description")
655
            };
656
            this.columnClasses = new Class[]{
657
                String.class,
658
                String.class,
659
                String.class,
660
                Boolean.class,
661
                String.class
662
            };
663
            this.reportListener = new ChangeListener() {
664
                @Override
665
                public void stateChanged(final ChangeEvent e) {
666
                    if (!SwingUtilities.isEventDispatchThread()) {
667
                        SwingUtilities.invokeLater(new Runnable() {
668
                            @Override
669
                            public void run() {
670
                                stateChanged(e);
671
                            }
672
                        });
673
                        return;
674
                    }
675
                    fireTableChanged();
676
                }
677
            };
678
        }
679

    
680
        public void setReport(TopologyReport report) {
681
            if (this.report != null) {
682
                this.report.removeChangeListener(this.reportListener);
683
            }
684
            this.report = report;
685
            this.lines = this.report;
686
            this.lines.addChangeListener(this.reportListener);
687
        }
688

    
689
        public void setFilter(String filter) {
690
            if (StringUtils.equals(filter, this.lastFilter)) {
691
                return;
692
            }
693
            this.lines = this.report.getLineSet(filter);
694
            this.lines.addChangeListener(this.reportListener);
695
            this.lastFilter = filter;
696
            this.fireTableChanged();
697
        }
698

    
699
        public TopologyReport getReport() {
700
            return this.report;
701
        }
702

    
703
        @Override
704
        public int getRowCount() {
705
            if (this.lines == null) {
706
                return 0;
707
            }
708
            return this.lines.size();
709
        }
710

    
711
        @Override
712
        public int getColumnCount() {
713
            return 5;
714
        }
715

    
716
        @Override
717
        public String getColumnName(int columnIndex) {
718
            return this.columnNames[columnIndex];
719
        }
720

    
721
        @Override
722
        public Class<?> getColumnClass(int columnIndex) {
723
            return this.columnClasses[columnIndex];
724
        }
725

    
726
        @Override
727
        public boolean isCellEditable(int rowIndex, int columnIndex) {
728
            return false;
729
        }
730

    
731
        @Override
732
        public Object getValueAt(int rowIndex, int columnIndex) {
733
            if (this.lines == null) {
734
                return "";
735
            }
736
            TopologyReportLine line = this.lines.get(rowIndex);
737
            switch (columnIndex) {
738
                case 0:
739
                    return line.getRule().getName();
740
                case 1:
741
                    return line.getDataSet1().getName();
742
                case 2:
743
                    if (line.getDataSet2() == null) {
744
                        return "";
745
                    }
746
                    return line.getDataSet2().getName();
747
                case 3:
748
                    return line.isException();
749
                case 4:
750
                    return line.getDescription();
751
                default:
752
                    return "???";
753
            }
754
        }
755

    
756
        @Override
757
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
758
        }
759

    
760
        @Override
761
        public void addTableModelListener(TableModelListener l) {
762
            this.tableListeners.add(l);
763
        }
764

    
765
        @Override
766
        public void removeTableModelListener(TableModelListener l) {
767
            this.tableListeners.remove(l);
768
        }
769

    
770
        private void fireTableChanged() {
771
            saveCurrentSelection();
772
            for (TableModelListener tableListener : this.tableListeners) {
773
                tableListener.tableChanged(new TableModelEvent(this));
774
            }
775
            restoreCurrentSelection();
776
        }
777

    
778
        public TopologyReportLine getLine(int lineNum) {
779
            return this.lines.get(lineNum);
780
        }
781

    
782
    }
783

    
784
    private void saveCurrentSelection() {
785
        this.tblErrors.setSelectionModel(new DefaultListSelectionModel());
786
    }
787

    
788
    private void restoreCurrentSelection() {
789
        this.tblErrors.setSelectionModel(this.selection);
790
    }
791
    
792
    
793
    private void showErrorForm() {
794
        int n = this.tblErrors.getSelectedRow();
795
        if (n < 0) {
796
            return;
797
        }
798
        TopologyReportLine line = this.linesModel.getLine(n);
799
        DataStore store = line.getDataSet1().getStore();
800
        JFeaturesForm form;
801
        try {
802
            FeatureStore fStore = (FeatureStore) store;
803
            FeatureType fType = fStore.getDefaultFeatureType();
804
            ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
805
            FeatureAttributeDescriptor[] pk = fType.getPrimaryKey();
806
            
807
            if (pk==null) {
808
                //FIXME : Presentar mensaje al usuario. Como poner ventanas en JAVA
809
                //FIXME : Permitir tratar tablas en las reglas.
810
                return;
811
            }
812
                //FIXME : Falta gestionar cuando la clave primarias es de varios campos
813
                
814
            Feature feature = line.getFeature1().getFeature();
815
            String filter = builder.eq(
816
                    builder.variable(pk[0].getName()),
817
                    builder.constant(feature.get(pk[0].getName()))
818
            ).toString();
819
            
820
            form = this.createform(fStore);
821
            FeatureQuery query = fStore.createFeatureQuery(filter, null, true);
822
            form.setQuery(query);
823
            form.showForm(WindowManager.MODE.WINDOW);
824
        } catch (Exception ex) {
825
            LOGGER.warn("Can't create form", ex);
826
        } 
827
    }
828

    
829
    private JFeaturesForm createform(FeatureStore featureStore) throws CreateJFeatureFormException, ServiceException, DataException {
830
        final DataSwingManager swingManager = DALSwingLocator.getSwingManager();
831
        final JFeaturesForm form = swingManager.createJFeaturesForm(featureStore);
832
        form.getFormset().setAllowDelete(true);
833
        form.getFormset().setAllowNew(true);
834
        form.setPreferredSize(new Dimension(400, 300));
835
        return form;
836
    }
837
    
838
}