Statistics
| Revision:

gvsig-projects-pool / org.gvsig.online / trunk / org.gvsig.online / org.gvsig.online.swing / org.gvsig.online.swing.impl / src / main / java / org / gvsig / online / swing / impl / changes / RemoteChangesController.java @ 9512

History | View | Annotate | Download (43.8 KB)

1
/*
2
 * gvSIG. Desktop Geographic Information System.
3
 * 
4
 * Copyright (C) 2007-2020 gvSIG Association.
5
 * 
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 * 
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 * 
16
 * You should have received a copy of the GNU General Public License 
17
 * along with this program. If not, see <https://www.gnu.org/licenses/>. 
18
 * 
19
 * For any additional information, do not hesitate to contact us
20
 * at info AT gvsig.com, or visit our website www.gvsig.com.
21
 */
22
package org.gvsig.online.swing.impl.changes;
23

    
24
import java.awt.Component;
25
import java.awt.Cursor;
26
import java.awt.Dimension;
27
import java.awt.event.ActionEvent;
28
import java.awt.event.KeyAdapter;
29
import java.awt.event.KeyEvent;
30
import java.util.ArrayList;
31
import java.util.List;
32
import javax.swing.JButton;
33
import javax.swing.JLabel;
34
import javax.swing.JOptionPane;
35
import javax.swing.JTable;
36
import javax.swing.ListSelectionModel;
37
import javax.swing.SwingUtilities;
38
import javax.swing.event.ListSelectionEvent;
39
import javax.swing.event.TableModelEvent;
40
import javax.swing.event.TableModelListener;
41
import javax.swing.table.DefaultTableCellRenderer;
42
import javax.swing.table.TableModel;
43
import org.apache.commons.collections.CollectionUtils;
44
import org.apache.commons.lang3.mutable.MutableLong;
45
import org.apache.commons.lang3.mutable.MutableObject;
46
import org.gvsig.featureform.swing.JFeatureForm;
47
import org.gvsig.fmap.dal.feature.Feature;
48
import org.gvsig.fmap.dal.feature.FeatureStore;
49
import org.gvsig.fmap.dal.feature.FeatureType;
50
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
51
import org.gvsig.fmap.dal.swing.DALSwingLocator;
52
import org.gvsig.fmap.dal.swing.DataSwingManager;
53
import org.gvsig.fmap.geom.Geometry;
54
import org.gvsig.fmap.geom.GeometryLocator;
55
import org.gvsig.fmap.geom.GeometryUtils;
56
import org.gvsig.fmap.geom.aggregate.MultiPrimitive;
57
import org.gvsig.fmap.geom.primitive.Envelope;
58
import org.gvsig.json.Json;
59
import static org.gvsig.online.lib.api.OnlineManager.ERR_OK;
60
import static org.gvsig.online.lib.api.OnlineManager.OP_DELETE;
61
import org.gvsig.online.lib.api.OnlineRuntimeException;
62
import org.gvsig.online.lib.api.workingcopy.OnlineEntity;
63
import org.gvsig.online.lib.api.workingcopy.OnlineRemoteChange;
64
import org.gvsig.online.lib.api.workingcopy.OnlineWorkingcopy;
65
import org.gvsig.online.swing.api.OnlineSwingLocator;
66
import org.gvsig.online.swing.api.OnlineSwingManager;
67
import org.gvsig.online.swing.api.OnlineSwingServices;
68
import static org.gvsig.online.swing.api.OnlineSwingServices.HIGHLIGHT_REMOTE;
69
import static org.gvsig.online.swing.api.OnlineSwingServices.HIGHLIGHT_WORKSPACE;
70
import org.gvsig.online.swing.impl.OnlineSwingCommons;
71
import static org.gvsig.online.swing.impl.OnlineSwingCommons.cleanHighligthed;
72
import static org.gvsig.online.swing.impl.OnlineSwingCommons.getHTMLFontColorTag;
73
import static org.gvsig.online.swing.impl.OnlineSwingCommons.notInSwingThreadInvokeLater;
74
import static org.gvsig.online.swing.impl.OnlineSwingCommons.refreshDocument;
75
import static org.gvsig.online.swing.impl.OnlineSwingCommons.showAuthenticationErrors;
76
import static org.gvsig.online.swing.impl.changes.OnlineJChangesImpl.LOCAL_TAB_INDEX;
77
import org.gvsig.tools.ToolsLocator;
78
import org.gvsig.tools.dispose.DisposeUtils;
79
import org.gvsig.tools.dispose.impl.AbstractDisposable;
80
import org.gvsig.tools.dynform.DynFormLocator;
81
import org.gvsig.tools.dynform.JDynForm;
82
import org.gvsig.tools.dynobject.DynObject;
83
import org.gvsig.tools.exception.BaseException;
84
import org.gvsig.tools.i18n.I18nManager;
85
import org.gvsig.tools.swing.api.ToolsSwingLocator;
86
import org.gvsig.tools.swing.api.ToolsSwingManager;
87
import org.gvsig.tools.swing.api.pickercontroller.PickerController;
88
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
89
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
90
import org.gvsig.tools.task.SimpleTaskStatus;
91
import org.gvsig.tools.task.UserCancelTaskException;
92
import org.slf4j.Logger;
93
import org.slf4j.LoggerFactory;
94
import org.gvsig.online.lib.api.workingcopy.OnlineChanges;
95

    
96
/**
97
 *
98
 * @author gvSIG Team
99
 */
100
@SuppressWarnings("UseSpecificCatch")
101
public class RemoteChangesController extends AbstractDisposable {
102

    
103
    private static final Logger LOGGER = LoggerFactory.getLogger(RemoteChangesController.class);
104
    private static final int MAX_SELECTED_ROWS_TO_SHOW_GEOMETRIES = 200;
105

    
106
    private final PickerController<OnlineWorkingcopy> workspacePicker;
107
    private final JTable tblRemoteChanges;
108
    private final JButton btnRemoteShowForm;
109
    private final JButton btnRemoteUpdate;
110
    private final JButton btnRemoteMerge;
111
    private final JButton btnRemoteReloadChanges;
112
    private final JButton btnRemoteCheckAll;
113
    private final JButton btnRemoteUnCheckAll;
114

    
115
//    private OnlineChanges<OnlineRemoteChange> changes;
116

    
117
    private final JButton btnRemoteCleanChanges;
118
    private final OnlineJChangesImpl context;
119
    
120
    
121
    private final JButton btnRemoteZoom;
122
    private final JButton btnRemoteCenter;
123
    private final JButton btnRemoteHighlight;
124
    private final JButton btnRemoteCleanHighligthed;
125

    
126
    private final JLabel lblRemoteChangesCount;
127

    
128
    public RemoteChangesController(
129
            OnlineJChangesImpl context,
130
            PickerController<OnlineWorkingcopy> workspacePicker,
131
            JTable tblRemoteChanges,
132
            JButton btnRemoteCheckAll,
133
            JButton btnRemoteUnCheckAll,
134
            JButton btnRemoteReloadChanges,
135
            JButton btnRemoteCleanChanges,
136
            JButton btnRemoteUpdate,
137
            JButton btnRemoteMerge,
138
            JButton btnRemoteShowForm,
139
            JButton btnRemoteZoom,
140
            JButton btnRemoteCenter,
141
            JButton btnRemoteHighlight,
142
            JButton btnRemoteCleanHighligthed,
143
            JLabel lblRemoteChangesCount
144
    ) {
145
        this.context = context;
146

    
147
        this.workspacePicker = workspacePicker;
148

    
149
        this.tblRemoteChanges = tblRemoteChanges;
150
        this.btnRemoteCheckAll = btnRemoteCheckAll;
151
        this.btnRemoteUnCheckAll = btnRemoteUnCheckAll;
152
        
153
        this.btnRemoteCleanChanges = btnRemoteCleanChanges;
154
        this.btnRemoteReloadChanges = btnRemoteReloadChanges;
155

    
156
        this.btnRemoteUpdate = btnRemoteUpdate;
157
        this.btnRemoteMerge = btnRemoteMerge;
158
        this.btnRemoteShowForm = btnRemoteShowForm;
159

    
160
        this.btnRemoteZoom = btnRemoteZoom;
161
        this.btnRemoteCenter = btnRemoteCenter;
162
        this.btnRemoteHighlight = btnRemoteHighlight;
163
        
164
        this.btnRemoteCleanHighligthed = btnRemoteCleanHighligthed;
165

    
166
        this.lblRemoteChangesCount= lblRemoteChangesCount;
167
        
168
        initComponents();
169
    }
170

    
171
    public void alert(final String msg) {
172
        this.context.alert(msg);
173
    }
174

    
175
    public void message(final String msg) {
176
        this.context.message(msg);
177
    }
178

    
179
    private void initComponents() {
180
        I18nManager i18n = ToolsLocator.getI18nManager();
181

    
182
        this.btnRemoteCheckAll.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
183
        this.btnRemoteCleanChanges.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
184
        this.btnRemoteMerge.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
185
        this.btnRemoteReloadChanges.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
186
        this.btnRemoteShowForm.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
187
        this.btnRemoteUnCheckAll.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
188
        this.btnRemoteUpdate.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
189
        this.btnRemoteZoom.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
190
        this.btnRemoteCenter.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
191
        this.btnRemoteHighlight.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
192
        this.btnRemoteCleanHighligthed.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
193

    
194
        translate();
195

    
196
        this.tblRemoteChanges.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
197

    
198
        this.tblRemoteChanges.addKeyListener(new KeyAdapter() {
199
            @Override
200
            public void keyPressed(KeyEvent e) {
201
                if (e.getKeyCode() == KeyEvent.VK_SPACE) {
202
                    doToggleSelection();
203
                }
204
            }
205
        });
206

    
207
        this.tblRemoteChanges.getSelectionModel().addListSelectionListener((ListSelectionEvent e) -> {
208
            context.doUpdateComponents();
209
            doUpdateChangesCount();
210
        });
211
        
212
        this.btnRemoteCheckAll.addActionListener((ActionEvent e) -> {
213
            doCheckAll();
214
        });
215

    
216
        this.btnRemoteUnCheckAll.addActionListener((ActionEvent e) -> {
217
            doUnCheckAll();
218
        });
219

    
220
        this.btnRemoteReloadChanges.addActionListener((ActionEvent e) -> {
221
            doReloadChanges();
222
        });
223

    
224
        this.btnRemoteCleanChanges.addActionListener((ActionEvent e) -> {
225
            doCleanChanges();
226
        });
227

    
228
        this.btnRemoteUpdate.addActionListener((ActionEvent e) -> {
229
            doUpdate();
230
        });
231

    
232
        this.btnRemoteMerge.addActionListener((ActionEvent e) -> {
233
            doMerge();
234
        });
235

    
236
        this.btnRemoteShowForm.addActionListener((ActionEvent e) -> {
237
            doShowForm();
238
        });
239
        
240
        this.btnRemoteZoom.addActionListener((ActionEvent e) -> {
241
            doZoomToSelectedChange();
242
        });
243

    
244
        this.btnRemoteCenter.addActionListener((ActionEvent e) -> {
245
            doCenterToSelectedChange();
246
        });
247
        
248
        this.btnRemoteHighlight.addActionListener((ActionEvent e) -> {
249
            doHighLightSelectedChange();
250
        });
251
        
252
        this.btnRemoteCleanHighligthed.addActionListener((ActionEvent e) -> {
253
            cleanHighligthed();
254
        });
255

    
256
        context.doUpdateComponents();
257

    
258
        SwingUtilities.invokeLater(() -> {
259
            doReloadChanges();
260
            message(i18n.getTranslation("_Ready"));
261
            this.lblRemoteChangesCount.setText("");
262
        });
263

    
264
    }
265
    
266
    public void translate() {
267
        ToolsSwingManager swingManager = ToolsSwingLocator.getToolsSwingManager();
268

    
269
        swingManager.translate(this.btnRemoteCheckAll);
270
        swingManager.translate(this.btnRemoteUpdate);
271
        swingManager.translate(this.btnRemoteCleanChanges);
272
        swingManager.translate(this.btnRemoteReloadChanges);
273
        swingManager.translate(this.btnRemoteMerge);
274
        swingManager.translate(this.btnRemoteShowForm);
275
        swingManager.translate(this.btnRemoteUnCheckAll);
276
        swingManager.translate(this.btnRemoteCenter);
277
        swingManager.translate(this.btnRemoteHighlight);
278
        swingManager.translate(this.btnRemoteZoom);
279
        swingManager.translate(this.btnRemoteCleanHighligthed);
280
    }
281

    
282
    private OnlineWorkingcopy getUndisposableWorkspace() {
283
        OnlineWorkingcopy ws = this.context.getWorkspace();
284
        DisposeUtils.disposeQuietly(ws);
285
//        LOGGER.info("ws.references = " + DisposeUtils.getReferences(ws));
286
        return ws;
287
    }
288

    
289
    /* friend */ void doUpdateComponents() {
290
        if (notInSwingThreadInvokeLater(() -> {
291
            doUpdateComponents();
292
        })) {
293
            return;
294
        }
295
        OnlineWorkingcopy ws;
296
        for (int i = 0; i < 10; i++) {
297

    
298
            try {
299
                RemoteChangesTableModel tableModel = (RemoteChangesTableModel) this.tblRemoteChanges.getModel();
300
                this.context.setVisibleStatus(context.processing);
301
                this.context.btnClose.setEnabled(!context.processing);
302
                ws = this.getUndisposableWorkspace();
303
                List<OnlineEntity> checkedEntities = context.getEntitySelector().getCheckedEntities();
304

    
305
                this.btnRemoteCheckAll.setEnabled(!context.processing && !tableModel.isEmpty());
306
                this.btnRemoteUnCheckAll.setEnabled(!context.processing && !tableModel.isEmpty());
307

    
308
                this.btnRemoteReloadChanges.setEnabled(!context.processing && ws != null);
309
                this.btnRemoteCleanChanges.setEnabled(!context.processing && ws != null);
310

    
311
                //Show form
312
                boolean enableShowForm = false;
313
                int row = this.tblRemoteChanges.getSelectedRow();
314
                if (row >= 0) {
315
                    enableShowForm = true;
316
                }
317
                this.btnRemoteShowForm.setEnabled(!context.processing && enableShowForm);
318

    
319
                context.getEntitySelector().setEnabled(!context.processing);
320
                this.tblRemoteChanges.setEnabled(!context.processing);
321
                this.workspacePicker.setEnabled(!context.processing);
322

    
323
                if (CollectionUtils.isEmpty(checkedEntities)) {
324
                    this.btnRemoteMerge.setEnabled(false);
325
                    this.btnRemoteUpdate.setEnabled(false);
326
                } else {
327
                    MutableObject<String> msg = new MutableObject<>();
328
                    for (OnlineEntity checkedEntity : checkedEntities) {
329
                        if (!ws.canUpdate(msg, checkedEntity.getEntityName())) {
330
                            break;
331
                        }
332
                    }
333
                    if (msg.getValue() != null) {
334
                        this.btnRemoteMerge.setEnabled(false);
335
                        this.btnRemoteUpdate.setEnabled(false);
336
                        this.alert(msg.getValue());
337
                    } else {
338
                        if (checkedEntities.size() == 1) {
339
                            OnlineEntity checkedEntity = checkedEntities.get(0);
340
                            if (ws.updateNeedMerge(checkedEntity.getEntityName())) {
341
                                this.btnRemoteMerge.setEnabled(!context.processing);
342
                                this.btnRemoteUpdate.setEnabled(false);
343
                            } else {
344
                                this.btnRemoteMerge.setEnabled(false);
345
                                this.btnRemoteUpdate.setEnabled(!context.processing && !tableModel.isSelectionEmpty());
346
                            }
347
                        } else {
348
                            this.btnRemoteMerge.setEnabled(false);
349
                            this.btnRemoteUpdate.setEnabled(!context.processing && !tableModel.isSelectionEmpty());
350
                            for (OnlineEntity checkedEntity : checkedEntities) {
351
                                if (ws.updateNeedMerge(checkedEntity.getEntityName())) {
352
                                    this.btnRemoteMerge.setEnabled(!context.processing);
353
                                    this.btnRemoteUpdate.setEnabled(false);
354
                                    break;
355
                                }
356
                            }
357
                        }
358
                    }
359
                }
360

    
361
                Geometry repoGeom = getRepositoryGeometryOfSelectedChange();
362
                Geometry wsGeom = getWorkspaceGeometryOfSelectedChange();
363
                Geometry bbox = OnlineSwingCommons.createBBox(repoGeom, wsGeom);
364
                this.btnRemoteZoom.setEnabled(!context.processing); // && bbox != null);
365
                this.btnRemoteCenter.setEnabled(!context.processing); // && bbox != null);
366
                this.btnRemoteHighlight.setEnabled(!context.processing && bbox != null);
367
                this.btnRemoteCleanHighligthed.setEnabled(!context.processing);
368
            } catch (ConcurrentDataModificationException e3) {
369
                try {
370
                    Thread.sleep(1000);
371
                } catch (InterruptedException ex) {
372
                    //Do nothing
373
                }
374
                LOGGER.info("Retrying doUpdateComponents "+i);
375
                continue;
376
            } catch (OnlineRuntimeException e1) {
377
                LOGGER.warn("Can't updating components.", e1);
378
                if (showAuthenticationErrors("_Online_Changes", e1)) {
379
                    this.workspacePicker.set(null);
380
//                doChangeWorkspace();
381
                }
382
            } catch (Exception e2) {
383
                LOGGER.warn("Can't updating components.", e2);
384
            }
385
            break;
386
        }
387

    
388
    }
389

    
390
    private void doToggleSelection() {
391
        Thread task = new Thread(() -> {
392
            try {
393
                context.processing = true;
394
                context.doUpdateComponents();
395
                ListSelectionModel selectionModel = this.tblRemoteChanges.getSelectionModel();
396
                RemoteChangesTableModel model = (RemoteChangesTableModel) this.tblRemoteChanges.getModel();
397
                model.toggleSelection(selectionModel);
398
            } finally {
399
                context.processing = false;
400
                context.doUpdateComponents();
401
            }
402
        }, "OnlineToggleSelectionRemoteChanges");
403
        task.start();
404
    }
405

    
406
//    private Iterator<Long> getChangesSelectionIterator() {
407
//        ListSelectionModel selection = this.tblRemoteChanges.getSelectionModel();
408
//        return new Iterator<Long>() {
409
//            long n = selection.getMinSelectionIndex();
410
//
411
//            @Override
412
//            public boolean hasNext() {
413
//                while (n <= selection.getMaxSelectionIndex()) {
414
//                    if (selection.isSelectedIndex((int) n)) {
415
//                        return true;
416
//                    }
417
//                    n++;
418
//                }
419
//                return false;
420
//            }
421
//
422
//            @Override
423
//            public Long next() {
424
//                if (n > selection.getMaxSelectionIndex()) {
425
//                    throw new IllegalStateException();
426
//                }
427
//                return n++;
428
//            }
429
//        };
430
//    }
431
//
432
//    private Iterator<Long> getRowsIterator() {
433
//        long size = changes.size64();
434
//        return new Iterator<Long>() {
435
//            long n = 0;
436
//
437
//            @Override
438
//            public boolean hasNext() {
439
//                return (n < size);
440
//            }
441
//
442
//            @Override
443
//            public Long next() {
444
//                return n++;
445
//            }
446
//        };
447
//    }
448

    
449
    private void doCheckAll() {
450
        Thread task = new Thread(() -> {
451
            try {
452
                context.processing = true;
453
                context.doUpdateComponents();
454
                RemoteChangesTableModel model = (RemoteChangesTableModel) this.tblRemoteChanges.getModel();
455
                model.selectAll();
456
            } finally {
457
                context.processing = false;
458
                context.doUpdateComponents();
459
            }
460
        }, "OnlineCheckAllRemoteChanges");
461
        task.start();
462
    }
463

    
464
    private void doUnCheckAll() {
465
        Thread task = new Thread(() -> {
466
            try {
467
                context.processing = true;
468
                context.doUpdateComponents();
469
                RemoteChangesTableModel model = (RemoteChangesTableModel) this.tblRemoteChanges.getModel();
470
                model.deselectAll();
471
            } finally {
472
                context.processing = false;
473
                context.doUpdateComponents();
474
            }
475
        }, "OnlineCheckAllRemoteChanges");
476
        task.start();
477
    }
478

    
479
    private void doUpdate() {
480
        OnlineWorkingcopy ws = getUndisposableWorkspace();
481
        if (ws == null) {
482
            return;
483
        }
484
        List<OnlineEntity> checkedEntities = context.getEntitySelector().getCheckedEntities();
485
        if ( CollectionUtils.isEmpty(checkedEntities) ) {
486
            return;
487
        }
488

    
489
        this.tblRemoteChanges.setModel(createEmptyTableModel());
490

    
491
        SimpleTaskStatus taskStatus = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("_Download_changes");
492
        Thread task = new Thread(() -> {
493
            try {
494
                taskStatus.setAutoremove(true);
495
                taskStatus.add();
496
                context.setTaskStatus(taskStatus);
497
                context.processing = true;
498
                context.doUpdateComponents();
499
                int r = ERR_OK;
500
                for (OnlineEntity checkedEntity : checkedEntities) {
501
                    r = ws.update(checkedEntity.getEntityName(), taskStatus);
502
                    if( r!=ERR_OK ) {
503
                        break;
504
                    }
505
                }
506
                doPostUpdate(checkedEntities, r);
507
                taskStatus.terminate();
508
            } catch(UserCancelTaskException ex) {
509
                LOGGER.warn("User cancelled");
510
                taskStatus.cancel();
511
            } catch(Exception ex) {
512
                taskStatus.abort();
513
            } finally {
514
                context.processing = false;
515
                context.doUpdateComponents();
516
            }
517
        }, "OnlineUpdate");
518
        context.processing = true;
519
        context.doUpdateComponents();
520
        task.start();
521
    }
522

    
523
    private void doPostUpdate(List<OnlineEntity> checkedEntities, int updateStatus) {
524
        if (notInSwingThreadInvokeLater(() -> {doPostUpdate(checkedEntities, updateStatus);})) {
525
            return;
526
        }
527
        if (updateStatus == ERR_OK) {
528
            context.setVisibleStatus(false);
529
        }
530
        OnlineWorkingcopy ws = getUndisposableWorkspace();
531
        
532
        doReloadChanges();
533

    
534
        for (OnlineEntity checkedEntity : checkedEntities) {
535
            FeatureStore store = ws.getFeatureStore(checkedEntity.getEntityName());
536
            refreshDocument(store);
537
        }
538
        
539
        context.doUpdateComponents();
540
        context.updateLocalChangesTable();
541
        cleanHighligthed();        
542
    }
543

    
544

    
545
    private void doMerge() {
546
        OnlineWorkingcopy ws = getUndisposableWorkspace();
547
        if (ws == null) {
548
            return;
549
        }
550
        List<OnlineEntity> checkedEntities = context.getEntitySelector().getCheckedEntities();
551
        if ( CollectionUtils.isEmpty(checkedEntities) ) {
552
            return;
553
        }
554
//        if( checkedEntities.size()!=1 ) {
555
//            ThreadSafeDialogsManager dialogsManager = ToolsSwingLocator.getThreadSafeDialogsManager();
556
//            I18nManager i18n = ToolsLocator.getI18nManager();
557
//            dialogsManager.messageDialog(
558
//                    i18n.getTranslation("_Cant_merge_with_more_a_table_selected"), 
559
//                    null, 
560
//                    i18n.getTranslation("_Online_Merge"), 
561
//                    JOptionPane.WARNING_MESSAGE
562
//            );
563
//            return;
564
//        }
565
//        OnlineEntity entity = checkedEntities.get(0);
566
//        String tableName = entity.getEntityName();
567

    
568
        this.tblRemoteChanges.setModel(createEmptyTableModel());
569

    
570
        Thread task = new Thread(() -> {
571
            try {
572
                context.processing = true;
573
                context.doUpdateComponents();
574
                MutableLong localChangesCreated = new MutableLong(0);
575
                List<OnlineEntity> entitiesWithLocalChanges = new ArrayList<>();
576
                int r = ERR_OK;
577
                for (OnlineEntity entity : checkedEntities) {
578
                    String tableName = entity.getEntityName();
579
                    long lchanges = localChangesCreated.getValue();
580
                    r = getUndisposableWorkspace().merge(
581
                            tableName,
582
                            localChangesCreated,
583
                            this.context.getTaskStatusController().getSimpleTaskStatus()
584
                    );
585
                    if( r!=ERR_OK ) {
586
                        break;
587
                    }
588
                    if( lchanges!=localChangesCreated.getValue() ) {
589
                        entitiesWithLocalChanges.add(entity);
590
                    }
591
                }
592
                doPostMerge(checkedEntities, entitiesWithLocalChanges, r, localChangesCreated.getValue());
593
            } catch(UserCancelTaskException ex) {
594
                LOGGER.warn("User cancelled");
595
            } finally {
596
                context.processing = false;
597
                context.doUpdateComponents();
598
            }
599
        }, "OnlineMerge");
600
        context.processing = true;
601
        context.doUpdateComponents();
602
        task.start();
603
    }
604

    
605
    private void doPostMerge(List<OnlineEntity> checkedEntities, List<OnlineEntity> entitiesWithLocalChanges, int mergeStatus, long localChangesCreated) {
606
        if (notInSwingThreadInvokeLater(() -> {doPostMerge(checkedEntities, entitiesWithLocalChanges, mergeStatus, localChangesCreated);})) {
607
            return;
608
        }
609
        if (mergeStatus == ERR_OK) {
610
            this.context.setVisibleStatus(false);
611
        }
612
        doReloadChanges();
613
        OnlineWorkingcopy ws = getUndisposableWorkspace();
614
        for (OnlineEntity entity : checkedEntities) {
615
            FeatureStore store = ws.getFeatureStore(entity.getEntityName());
616
            refreshDocument(store);
617
        }
618
//        FeatureStore store = getUndisposableWorkspace().getFeatureStore(entity.getEntityName());
619
//        refreshDocument(store);
620
        
621
        if(localChangesCreated>0){
622
            ThreadSafeDialogsManager dialogsManager = ToolsSwingLocator.getThreadSafeDialogsManager();
623
            I18nManager i18n = ToolsLocator.getI18nManager();
624
            dialogsManager.messageDialog(
625
                    i18n.getTranslation("_The_process_has_modified_local_changes_that_would_need_to_be_committed_to_the_repository"), 
626
                    null, 
627
                    i18n.getTranslation("_Online_Merge"), 
628
                    JOptionPane.INFORMATION_MESSAGE, 
629
                    "Online_merge_need_commit");
630
            context.selectTab(LOCAL_TAB_INDEX);
631
            context.selectOnlyALocalEntity(entitiesWithLocalChanges);
632
        }
633
        context.doUpdateComponents();
634
        context.updateLocalChangesTable();
635
        cleanHighligthed();
636
    }
637

    
638
    private void doShowForm() {
639
        RemoteChangesTableModel model = (RemoteChangesTableModel)this.tblRemoteChanges.getModel();
640
        int row = this.tblRemoteChanges.getSelectedRow();
641
        OnlineRemoteChange change = model.getRow(row);
642
        if(change == null) {
643
            return;
644
        }
645
        if (change.getOperation() == OP_DELETE) {
646
            return;
647
        }
648
        OnlineWorkingcopy ws = this.getUndisposableWorkspace();
649
        if (ws == null) {
650
            return;
651
        }
652
        OnlineEntity entity = ws.getWorkspaceEntityByCode(change.getEntityCode());
653

    
654
        if (entity == null) {
655
            OnlineEntity repoEntity = ws.getEntity(change.getEntityCode());
656
            FeatureType featureType = repoEntity.getFeatureType();
657
            JDynForm form = DynFormLocator.getDynFormManager().createJDynForm(featureType);
658
            DynObject values = ToolsLocator.getDynObjectManager().createDynObject(featureType);
659
            Json.addAll(values, change.getRelatedFeatureDataAsJson());
660
            form.setValues(values);
661
            form.setReadOnly(true);
662
            WindowManager winManager = ToolsSwingLocator.getWindowManager();
663
            form.asJComponent().setPreferredSize(new Dimension(400, 200));
664
            winManager.showWindow(form.asJComponent(), "Remote change: " + change.getLabel(), WindowManager.MODE.WINDOW);
665
            return;
666
        }
667

    
668
        FeatureStore store = null;
669
        try {
670
            DataSwingManager dataSwingManager = DALSwingLocator.getDataSwingManager();
671

    
672
            store = ws.openFeatureStore(entity.getEntityName(),false);
673
            Feature feature = store.createNewFeature(change.getRelatedFeatureDataAsJson());
674
            JFeatureForm form = dataSwingManager.createJFeatureForm(feature);
675
            form.getDynForm().setReadOnly(true);
676
            WindowManager winManager = ToolsSwingLocator.getWindowManager();
677
            form.asJComponent().setPreferredSize(new Dimension(400, 200));
678
            winManager.showWindow(form.asJComponent(), "Remote change: " + change.getLabel(), WindowManager.MODE.WINDOW);
679
        } catch (Exception ex) {
680
            LOGGER.warn("Can't show form for change '" + change.getCode() + "'.", ex);
681
        } finally {
682
            DisposeUtils.disposeQuietly(store);
683
        }
684

    
685
    }
686

    
687
    protected void doReloadChanges() {
688
        OnlineWorkingcopy ws = this.getUndisposableWorkspace();
689
        if (ws == null) {
690
            return;
691
        }
692
        I18nManager i18n = ToolsLocator.getI18nManager();
693
        RemoteChangesTableModel changesModel = createTableModel();
694
        this.tblRemoteChanges.setModel(changesModel);
695
        int columns = this.tblRemoteChanges.getColumnModel().getColumnCount();
696
        for (int i = 1; i < columns; i++) {
697
            this.tblRemoteChanges.getColumnModel().getColumn(i).setCellRenderer(new DefaultTableCellRenderer() {
698
                @Override
699
                public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
700
                    Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
701
                    OnlineRemoteChange changeRow = null;
702
                    try {
703
                        changeRow = changesModel.getRow(row);
704
                    } catch (IndexOutOfBoundsException ex) {
705
                        //Do nothing
706
                    }
707
                    if(changeRow != null){
708
                        OnlineSwingCommons.setColorCompoment(c, changeRow.getStatus());
709
                    }
710
                    return c;
711
                }
712
            });
713
        }
714

    
715
        context.doUpdateComponents();
716
        doUpdateChangesCount();
717
        context.message(i18n.getTranslation(
718
                "_Repository_changes_list_updated", 
719
                new String[] { String.valueOf(changesModel.getRowCount()) }
720
            )
721
        );
722
    }
723
    
724
    private void doUpdateChangesCount() {
725
        TableModel model = tblRemoteChanges.getModel();
726
        int selectedCounts = tblRemoteChanges.getSelectedRowCount();
727
        if(selectedCounts<1){
728
            this.lblRemoteChangesCount.setText(String.valueOf(model.getRowCount()));
729
        } else if (selectedCounts < MAX_SELECTED_ROWS_TO_SHOW_GEOMETRIES) {
730
            this.lblRemoteChangesCount.setText("<html>"+getHTMLFontColorTag(java.awt.Color.GREEN.darker(),true, false, String.valueOf(selectedCounts))+"/"+model.getRowCount()+"</html>");
731
        } else {
732
            this.lblRemoteChangesCount.setText(selectedCounts+"/"+model.getRowCount());
733
        }
734
        
735
    }
736

    
737
    protected RemoteChangesTableModel createEmptyTableModel() {
738
        OnlineWorkingcopy ws = this.getUndisposableWorkspace();
739
        if (ws == null) {
740
            return null;
741
        }
742
        RemoteChangesTableModel changesModel = new RemoteChangesTableModel(ws);
743
        return changesModel;
744
    }
745
    
746
    protected RemoteChangesTableModel createTableModel() {
747
        OnlineWorkingcopy ws = this.getUndisposableWorkspace();
748
        if (ws == null) {
749
            return null;
750
        }
751
        List<OnlineEntity> checkedEntities = context.getEntitySelector().getCheckedEntities();
752
        if ( CollectionUtils.isEmpty(checkedEntities) ) {
753
            return new RemoteChangesTableModel(ws);
754
        }
755
        
756
        message("Reloading list of remote changes...");
757
        OnlineChanges<OnlineRemoteChange> theChanges = ws.getRemoteChangesByEntity(
758
            checkedEntities.stream()
759
                .map((t) -> {return t.getEntityName();})
760
                .toArray((n) -> { return new String[n];})
761
        );
762
        RemoteChangesTableModel changesModel = new RemoteChangesTableModel(theChanges, ws);
763
        changesModel.addTableModelListener(new TableModelListener() {
764
            @Override
765
            public void tableChanged(TableModelEvent e) {
766
                context.doUpdateComponents();
767
            }
768
        });
769
        return changesModel;
770
    }
771

    
772
    private List<OnlineEntity>  getWorkspaceCheckedEntities() {
773
        OnlineWorkingcopy ws = this.getUndisposableWorkspace();
774
        if (ws == null) {
775
            return null;
776
        }
777
        List<OnlineEntity> checkedEntities = context.getEntitySelector().getCheckedEntities();
778
        if ( CollectionUtils.isEmpty(checkedEntities) ) {
779
            return null;
780
        }
781
        List<OnlineEntity> workspaceCheckedEntities = new ArrayList<>();
782
        for (OnlineEntity entity : checkedEntities) {
783
            if( ws.getWorkspaceEntityByCode(entity.getEntityCode())!=null ) {
784
                workspaceCheckedEntities.add(entity);
785
            }
786
        }
787
        if ( CollectionUtils.isEmpty(workspaceCheckedEntities) ) {
788
            return null;
789
        }
790
        return workspaceCheckedEntities;
791
    }
792
    
793
//    private List<OnlineEntity>  getRepositoryCheckedEntities() {
794
//        OnlineWorkingcopy ws = this.getUndisposableWorkspace();
795
//        if (ws == null) {
796
//            return null;
797
//        }
798
//        List<OnlineEntity> checkedEntities = entitySelector.getCheckedEntities();
799
//        if ( CollectionUtils.isEmpty(checkedEntities) ) {
800
//            return null;
801
//        }
802
//        List<OnlineEntity> workspaceCheckedEntities = new ArrayList<>();
803
//        for (OnlineEntity entity : checkedEntities) {
804
//            if( ws.getWorkspaceEntityByCode(entity.getEntityCode())==null ) {
805
//                workspaceCheckedEntities.add(entity);
806
//            }
807
//        }
808
//        if ( CollectionUtils.isEmpty(workspaceCheckedEntities) ) {
809
//            return null;
810
//        }
811
//        return workspaceCheckedEntities;
812
//    }
813

    
814
    private void doCleanChanges() {
815
        OnlineWorkingcopy ws = this.getUndisposableWorkspace();
816
        if (ws == null) {
817
            return;
818
        }
819
        List<OnlineEntity> entitiesToCleanChanges = this.getWorkspaceCheckedEntities();
820
        if ( CollectionUtils.isEmpty(entitiesToCleanChanges) ) {
821
            return;
822
        }
823
        Thread task = new Thread(() -> {
824
            try {
825
                RemoteChangesTableModel model = (RemoteChangesTableModel) tblRemoteChanges.getModel();
826
                context.processing = true;
827
                context.doUpdateComponents();
828
                for (OnlineEntity checkedEntity : entitiesToCleanChanges) {
829
                    message("Removing list of remote changes from selected tables" + checkedEntity.getEntityName() + "...");
830
//                    ws.removeRemoteChanges(checkedEntity.getEntityName());
831
                    model.removeRemoteChanges(checkedEntity.getEntityName());
832
                }
833
//                doReloadChanges();
834
                context.doReloadTables();
835
                message("Ready.");
836
            } finally {
837
                context.processing = false;
838
                context.doUpdateComponents();
839
            }
840
        }, "OnlineUpdateClean");
841
        task.start();
842
    }
843

    
844
//    private void doReloadTables() {
845
//        OnlineWorkingcopy ws = this.getUndisposableWorkspace();
846
//        if (ws == null) {
847
//            this.entitySelector.setWorkspace(null);
848
//            return;
849
//        }
850
//        this.entitySelector.reloadEntities();
851
////        context.doUpdateComponents();
852
//    }
853

    
854
    public boolean isProcessing() {
855
        return context.processing;
856
    }
857
    
858
    private Geometry getRepositoryGeometryOfSelectedChange() {
859
        Geometry geom = null;
860
        try {
861
            RemoteChangesTableModel model = (RemoteChangesTableModel) tblRemoteChanges.getModel();
862
            if( this.tblRemoteChanges.getSelectedRowCount()>1 && this.tblRemoteChanges.getSelectedRowCount()<MAX_SELECTED_ROWS_TO_SHOW_GEOMETRIES ) {
863
                for (int selectedRow : this.tblRemoteChanges.getSelectedRows()) {
864
                    OnlineRemoteChange change = model.getRow(selectedRow);
865
                    Geometry currentGeom = change.getGeometry();
866
                    if( currentGeom!=null ) {
867
                        if( geom == null ) {
868
                            int type = currentGeom.getType();
869
                            if( GeometryUtils.isSubtype(Geometry.TYPES.POINT, type) || GeometryUtils.isSubtype(Geometry.TYPES.MULTIPOINT, type)) {
870
                                    geom = GeometryLocator.getGeometryManager().createMultiPoint(currentGeom.getGeometryType().getSubType());
871
                            } else if( GeometryUtils.isSubtype(Geometry.TYPES.LINE, type) || GeometryUtils.isSubtype(Geometry.TYPES.MULTILINE, type)) {
872
                                geom = GeometryLocator.getGeometryManager().createMultiCurve(currentGeom.getGeometryType().getSubType());
873
                            } else if( GeometryUtils.isSubtype(Geometry.TYPES.SURFACE, type) || GeometryUtils.isSubtype(Geometry.TYPES.MULTISURFACE, type)) {
874
                                geom = GeometryLocator.getGeometryManager().createMultiSurface(currentGeom.getGeometryType().getSubType());
875
                            } else {
876
                                return geom;
877
                            }
878
                        }
879
                        ((MultiPrimitive)geom).addPrimitives(currentGeom);
880
                    }
881
                }
882
            } else {
883
                int selected = this.tblRemoteChanges.getSelectedRow();
884
                if(selected >= 0){
885
                    OnlineRemoteChange change = model.getRow(selected);
886
                    geom = change.getGeometry();
887
                }
888
            }
889
            return geom;
890
        } catch (Exception ex) {
891
            return geom;
892
        }
893
    }
894

    
895
    private Envelope getEnvelopeOfAllRepositoryChanges() {
896
        Envelope env = GeometryUtils.createEnvelope(Geometry.SUBTYPES.GEOM2D);
897
        try {
898
            RemoteChangesTableModel model = (RemoteChangesTableModel) tblRemoteChanges.getModel();
899
            OnlineChanges<OnlineRemoteChange> changes = model.getChanges();
900
            for (int i = 0; i < changes.size64(); i++) {
901
                OnlineRemoteChange change = changes.get64(i);
902
                Geometry currentGeom = change.getGeometry();
903
                env.add(currentGeom);
904
            }
905
            return env;
906
        } catch (Exception ex) {
907
            return env;
908
        }
909
    }
910
    
911
    private Geometry getWorkspaceGeometryOfSelectedChange() {
912
        Geometry geom = null;
913
        try {
914
            OnlineWorkingcopy ws = getUndisposableWorkspace();
915
            RemoteChangesTableModel model = (RemoteChangesTableModel) tblRemoteChanges.getModel();
916
            if( this.tblRemoteChanges.getSelectedRowCount()>1 && this.tblRemoteChanges.getSelectedRowCount()<MAX_SELECTED_ROWS_TO_SHOW_GEOMETRIES ) {
917
                for (int selectedRow : this.tblRemoteChanges.getSelectedRows()) {
918
                    OnlineRemoteChange change = model.getRow(selectedRow);
919
                    Feature f = ws.getRelatedFeature(change);
920
                    if(f!= null){
921
                        Geometry currentGeom = f.getDefaultGeometry();
922
                        if( currentGeom!=null ) {
923
                            if( geom == null ) {
924
                                int type = currentGeom.getType();
925
                                if( GeometryUtils.isSubtype(Geometry.TYPES.POINT, type) || GeometryUtils.isSubtype(Geometry.TYPES.MULTIPOINT, type)) {
926
                                        geom = GeometryLocator.getGeometryManager().createMultiPoint(currentGeom.getGeometryType().getSubType());
927
                                } else if( GeometryUtils.isSubtype(Geometry.TYPES.LINE, type) || GeometryUtils.isSubtype(Geometry.TYPES.MULTILINE, type)) {
928
                                    geom = GeometryLocator.getGeometryManager().createMultiCurve(currentGeom.getGeometryType().getSubType());
929
                                } else if( GeometryUtils.isSubtype(Geometry.TYPES.SURFACE, type) || GeometryUtils.isSubtype(Geometry.TYPES.MULTISURFACE, type)) {
930
                                    geom = GeometryLocator.getGeometryManager().createMultiSurface(currentGeom.getGeometryType().getSubType());
931
                                } else {
932
                                    return geom;
933
                                }
934
                            }
935
                            ((MultiPrimitive)geom).addPrimitives(currentGeom);
936
                        }
937
                    }
938
                }
939
            } else {
940
                int selected = this.tblRemoteChanges.getSelectedRow();
941
                if(selected >= 0){
942
                    OnlineRemoteChange change = model.getRow(selected);
943
                    Feature f = ws.getRelatedFeature(change);
944
                    if(f!= null){
945
                        geom = f.getDefaultGeometry();
946
                    }
947
                }
948
            }
949
            return geom;
950
        } catch (Exception ex) {
951
            return geom;
952
        }
953
    }
954
    
955
    private FeatureStore getWorkspaceStoreOfSelectedChange() {
956
        FeatureStore store = null;
957
        int selected = this.tblRemoteChanges.getSelectedRow();
958
        RemoteChangesTableModel model = (RemoteChangesTableModel) tblRemoteChanges.getModel();
959
        
960
        if(selected >= 0){
961
            OnlineRemoteChange change = model.getRow(selected);
962
            
963
            OnlineWorkingcopy ws = getUndisposableWorkspace();
964
            OnlineEntity entity = ws.getWorkspaceEntityByCode(change.getEntityCode());
965
            store = ws.openFeatureStore(entity.getEntityName(),false);
966
        }
967
        return store;
968
    }
969

    
970
    
971
    private void doZoomToSelectedChange() {
972
        cleanHighligthed();
973
        OnlineSwingManager swingManager = OnlineSwingLocator.getOnlineSwingManager();
974
        OnlineSwingServices services = swingManager.getDefaultServices();
975
        if(tblRemoteChanges.getSelectionModel().isSelectionEmpty()) {
976
            FeatureStore store = this.context.getWorkspaceStoreOfSelectedEntity();
977
            if(store == null){
978
                return;
979
            }
980
            Envelope env = getEnvelopeOfAllRepositoryChanges();
981
            services.zoomViewsHavingAStoreToGeometry(store, env.getBox2D());
982
            return;
983
        }
984
        FeatureStore store = getWorkspaceStoreOfSelectedChange();
985
        Geometry repoGeom = getRepositoryGeometryOfSelectedChange();
986
        Geometry geom = getWorkspaceGeometryOfSelectedChange();
987
        services.zoomViewsHavingAStoreToGeometry(store, OnlineSwingCommons.createBBox(repoGeom, geom));
988
        if(repoGeom != null){
989
            services.highlight(HIGHLIGHT_REMOTE, repoGeom, store);
990
        }
991
        if(geom != null){
992
            services.highlight(HIGHLIGHT_WORKSPACE, geom, store);
993
        }
994
    }
995

    
996
    private void doCenterToSelectedChange() {
997
        cleanHighligthed();
998
        OnlineSwingManager swingManager = OnlineSwingLocator.getOnlineSwingManager();
999
        OnlineSwingServices services = swingManager.getDefaultServices();
1000
        if(tblRemoteChanges.getSelectionModel().isSelectionEmpty()) {
1001
            FeatureStore store = this.context.getWorkspaceStoreOfSelectedEntity();
1002
            if(store == null){
1003
                return;
1004
            }
1005
            Envelope env = getEnvelopeOfAllRepositoryChanges();
1006
            services.centerViewsHavingAStoreToGeometry(store, env.getBox2D());
1007
            return;
1008
        }
1009
        FeatureStore store = getWorkspaceStoreOfSelectedChange();
1010
        Geometry repoGeom = getRepositoryGeometryOfSelectedChange();
1011
        Geometry geom = getWorkspaceGeometryOfSelectedChange();
1012
        services.centerViewsHavingAStoreToGeometry(store, OnlineSwingCommons.createBBox(repoGeom, geom));
1013
        if(repoGeom != null){
1014
            services.highlight(HIGHLIGHT_REMOTE, repoGeom, store);
1015
        }
1016
        if(geom != null){
1017
            services.highlight(HIGHLIGHT_WORKSPACE, geom, store);
1018
        }
1019
    }
1020

    
1021
    private void doHighLightSelectedChange() {
1022
        cleanHighligthed();
1023
        OnlineSwingManager swingManager = OnlineSwingLocator.getOnlineSwingManager();
1024
        OnlineSwingServices services = swingManager.getDefaultServices();
1025
        FeatureStore store = getWorkspaceStoreOfSelectedChange();
1026
        Geometry repoGeom = getRepositoryGeometryOfSelectedChange();
1027
        Geometry geom = getWorkspaceGeometryOfSelectedChange();
1028
        if(repoGeom != null){
1029
            services.highlight(HIGHLIGHT_REMOTE, repoGeom, store);
1030
        }
1031
        if(geom != null){
1032
            services.highlight(HIGHLIGHT_WORKSPACE, geom, store);
1033
        }
1034
    }
1035

    
1036
    @Override
1037
    protected void doDispose() throws BaseException {
1038
        //TODO: Dispose what is needed
1039
//        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1040
//        DisposeUtils.disposeQuietly(entitySelector);
1041
    }
1042

    
1043
}