Statistics
| Revision:

gvsig-projects-pool / org.gvsig.vcsgis / trunk / org.gvsig.vcsgis / org.gvsig.vcsgis.lib / org.gvsig.vcsgis.lib.impl / src / main / java / org / gvsig / vcsgis / lib / workspace / VCSGisWorkspaceImpl.java @ 3308

History | View | Annotate | Download (150 KB)

1
package org.gvsig.vcsgis.lib.workspace;
2

    
3
import java.sql.Timestamp;
4
import java.time.LocalDateTime;
5
import java.time.ZoneOffset;
6
import java.util.ArrayList;
7
import java.util.Collection;
8
import java.util.Collections;
9
import java.util.Comparator;
10
import java.util.HashMap;
11
import java.util.HashSet;
12
import java.util.Iterator;
13
import java.util.List;
14
import java.util.Map;
15
import java.util.Objects;
16
import java.util.Set;
17
import javax.json.JsonObject;
18
import org.apache.commons.lang3.StringUtils;
19
import org.apache.commons.lang3.mutable.MutableObject;
20
import org.gvsig.expressionevaluator.ExpressionBuilder;
21
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
22
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
23
import org.gvsig.expressionevaluator.ExpressionUtils;
24
import org.gvsig.fmap.dal.DALLocator;
25
import org.gvsig.fmap.dal.DataManager;
26
import org.gvsig.fmap.dal.DataTransaction;
27
import org.gvsig.fmap.dal.exception.DataException;
28
import org.gvsig.fmap.dal.feature.EditableFeature;
29
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
30
import org.gvsig.fmap.dal.feature.EditableFeatureType;
31
import org.gvsig.fmap.dal.feature.Feature;
32
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
33
import org.gvsig.fmap.dal.feature.FeatureQuery;
34
import org.gvsig.fmap.dal.feature.FeatureReference;
35
import org.gvsig.fmap.dal.feature.FeatureSet;
36
import org.gvsig.fmap.dal.feature.FeatureSet.DisposableFeatureSetIterable;
37
import org.gvsig.fmap.dal.feature.FeatureStore;
38
import static org.gvsig.fmap.dal.feature.FeatureStore.MODE_APPEND;
39
import static org.gvsig.fmap.dal.feature.FeatureStore.MODE_FULLEDIT;
40
import static org.gvsig.fmap.dal.feature.FeatureStore.MODE_PASS_THROUGH;
41
import org.gvsig.fmap.dal.feature.FeatureType;
42
import org.gvsig.fmap.dal.store.jdbc.JDBCNewStoreParameters;
43
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorerParameters;
44
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
45
import org.gvsig.fmap.dal.store.jdbc2.JDBCServerExplorer;
46
import org.gvsig.json.Json;
47
import org.gvsig.tools.ToolsLocator;
48
import org.gvsig.tools.dataTypes.DataTypes;
49
import org.gvsig.tools.dispose.DisposableIterable;
50
import org.gvsig.tools.dispose.DisposeUtils;
51
import org.gvsig.tools.i18n.I18nManager;
52
import org.gvsig.tools.logger.FilteredLogger;
53
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
54
import org.gvsig.tools.resourcesstorage.ResourcesStorage.Resource;
55
import org.gvsig.tools.swing.api.ChangeListenerHelper;
56
import org.gvsig.tools.swing.api.ChangeListenerSupport;
57
import org.gvsig.tools.swing.api.ToolsSwingLocator;
58
import org.gvsig.tools.task.SimpleTaskStatus;
59
import org.gvsig.tools.util.GetItemWithSize64;
60
import org.gvsig.tools.util.GetItemWithSizeAndIterator64;
61
import org.gvsig.vcsgis.lib.DisposableIterableAdapter;
62
import org.gvsig.vcsgis.lib.VCSGisChange;
63
import org.gvsig.vcsgis.lib.VCSGisCodeGenerator;
64
import org.gvsig.vcsgis.lib.VCSGisEntity;
65
import org.gvsig.vcsgis.lib.VCSGisEntityEditable;
66
import static org.gvsig.vcsgis.lib.VCSGisManager.DEFAULT_DATA_TABLE;
67
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_AUTHENTICATION_EXPIRED;
68
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANCELLED_BY_USER;
69
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_ADD_CHANGE;
70
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_AUTHENTICATE_USER;
71
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_COMMIT;
72
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_INSERT_CHANGE;
73
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_INSERT_FEATURES;
74
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_OPEN_CHANGES;
75
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_OPEN_ENTITIES;
76
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_OPEN_STORE;
77
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_PREPARE_UPDATE;
78
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_REMOVE_CHANGES;
79
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_REMOVE_ENTITY;
80
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_RETRIEVE_ENTITIES;
81
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_RETRIEVE_SOURCE_FEATURES;
82
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_REVERT;
83
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_UPDATE;
84
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_UPDATE_CLEAN;
85
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_UPDATE_ENTITIES;
86
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_ENTITY_ALREADY_EXISTS;
87
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_ENTITY_NOT_EXISTS;
88
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_ENTITY_NOT_HAS_VCSGISCODE;
89
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_INVALID_AUTHENTICATION_TOKEN;
90
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_INVALID_USERCODE;
91
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_NO_ERROR;
92
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_OK;
93
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_STORE_NOT_IN_VERSION_CONTROL;
94
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_UPDATE_NEED_MERGE;
95
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_USER_NOT_AUTHORIZED;
96
import static org.gvsig.vcsgis.lib.VCSGisManager.FEATURECODE_FIELD_NAME;
97
import static org.gvsig.vcsgis.lib.VCSGisManager.OP_ADD_ENTITY;
98
import static org.gvsig.vcsgis.lib.VCSGisManager.OP_DELETE;
99
import static org.gvsig.vcsgis.lib.VCSGisManager.OP_INSERT;
100
import static org.gvsig.vcsgis.lib.VCSGisManager.OP_UPDATE;
101
import static org.gvsig.vcsgis.lib.VCSGisManager.STATE_CONFLICT;
102
import static org.gvsig.vcsgis.lib.VCSGisManager.STATE_LOCAL_MODIFIED;
103
import static org.gvsig.vcsgis.lib.VCSGisManager.STATE_LOCAL_NEW;
104
import static org.gvsig.vcsgis.lib.VCSGisManager.STATE_LOCAL_OUTDATED;
105
import static org.gvsig.vcsgis.lib.VCSGisManager.STATE_LOCAL_OUTDATED_AND_MODIFIED;
106
import static org.gvsig.vcsgis.lib.VCSGisManager.STATE_LOCAL_UNMODIFIED;
107
import static org.gvsig.vcsgis.lib.VCSGisManagerImpl.INTERNAL_WORKSPACE_TABLES;
108
import org.gvsig.vcsgis.lib.VCSGisRevision;
109
import org.gvsig.vcsgis.lib.VCSGisRuntimeException;
110
import org.gvsig.vcsgis.lib.VCSGisUser;
111
import org.gvsig.vcsgis.lib.VCSGisUtils;
112
import org.gvsig.vcsgis.lib.repository.VCSGisRepository;
113
import org.gvsig.vcsgis.lib.repository.VCSGisRepositoryChange;
114
import org.gvsig.vcsgis.lib.repository.VCSGisRepositoryData;
115
import org.gvsig.vcsgis.lib.repository.localdb.VCSGisRepositoryLocaldb;
116
import org.gvsig.vcsgis.lib.repository.localdb.tables.EntitiesRepoTable;
117
import org.gvsig.vcsgis.lib.repository.requests.VCSGisCheckoutRequest;
118
import org.gvsig.vcsgis.lib.repository.requests.VCSGisCommitRequest;
119
import org.gvsig.vcsgis.lib.repository.requests.VCSGisEntitiesRequest;
120
import org.gvsig.vcsgis.lib.repository.requests.VCSGisHistoryRequest;
121
import org.gvsig.vcsgis.lib.repository.requests.VCSGisUpdateRequest;
122
import org.gvsig.vcsgis.lib.workspace.tables.EntitiesTable;
123
import org.gvsig.vcsgis.lib.workspace.tables.EntitiesTable.EntityRow;
124
import org.gvsig.vcsgis.lib.workspace.tables.LocalRevisionsTable;
125
import org.gvsig.vcsgis.lib.workspace.tables.LocalRevisionsTable.LocalRevisionRow;
126
import org.gvsig.vcsgis.lib.workspace.tables.RemoteChangesTable;
127
import static org.gvsig.vcsgis.lib.workspace.tables.RemoteChangesTable.COD_ENTITY;
128
import org.gvsig.vcsgis.lib.workspace.tables.RemoteChangesTable.RemoteChangeRow;
129
import org.gvsig.vcsgis.lib.workspace.tables.VarsTable;
130
import org.gvsig.vcsgis.lib.workspace.tables.WorkspaceChangesTable;
131
import org.gvsig.vcsgis.lib.workspace.tables.WorkspaceChangesTable.WorkspaceChangeRow;
132
import org.slf4j.Logger;
133
import org.slf4j.LoggerFactory;
134
import org.gvsig.vcsgis.lib.VCSGisUserIdentificationRequester;
135
import org.gvsig.vcsgis.lib.repository.requests.VCSGisAuthenticateRequest;
136
import org.gvsig.vcsgis.lib.repository.requests.VCSGisRequest;
137
import org.gvsig.vcsgis.lib.workspace.tables.TopologyplanTable;
138

    
139
/**
140
 *
141
 * @author gvSIG Team
142
 */
143
@SuppressWarnings({"UseSpecificCatch", "UnusedAssignment"})
144
public class VCSGisWorkspaceImpl implements VCSGisWorkspace {
145

    
146
    private static final Logger LOGGER = LoggerFactory.getLogger(VCSGisWorkspaceImpl.class);
147

    
148
    private final Map<String, FeatureStore> storesCache;
149
    private Map<String, EntityRow> workspaceEntitiesByName;
150
    private Map<String, EntityRow> workspaceEntitiesByCode;
151
    private Map<String, VCSGisEntity> repositoryEntitiesByCode;
152
    private Set<FeatureStore> storeIgnoreChanges;
153
    private JDBCServerExplorer wsexplorer;
154
    private String code;
155
    private final VCSGisRepository repository;
156
    private final String label;
157
    private final FilteredLogger logger;
158
    private final VCSGisCodeGenerator codeGenerator;
159
    private final ChangeListenerHelper workspaceEntitiesChangeListeners;
160
    private final ChangeListenerHelper repositoryEntitiesChangeListeners;
161

    
162
    private String currentUser;
163
    private String authenticationToken;
164
    private VCSGisUserIdentificationRequester userIdentificationRequester;
165
    
166
    
167
    public VCSGisWorkspaceImpl(JDBCServerExplorer wsexplorer, VCSGisCodeGenerator codeGenerator, VCSGisRepository repository, String label) {
168
        this.logger = new FilteredLogger(LOGGER, "VCSGisWorkspace", 100);
169
        this.logger.setInterval(10000);
170
        this.codeGenerator = codeGenerator;
171
        this.storesCache = new HashMap<>();
172
        this.code = createUniqueCode();
173
        this.wsexplorer = wsexplorer;
174
        this.repository = repository;
175
        this.label = label;
176
        this.workspaceEntitiesChangeListeners = ToolsSwingLocator.getToolsSwingManager().createChangeListenerHelper();
177
        this.repositoryEntitiesChangeListeners = ToolsSwingLocator.getToolsSwingManager().createChangeListenerHelper();
178
        this.currentUser = null;
179
        this.authenticationToken = null;
180
        this.userIdentificationRequester = null;
181
//        LOGGER.debug("===: CREATE WORKSPACE "+ hexId(this)+ " (init label='"+this.label+"')");
182
    }
183

    
184
    @SuppressWarnings("LeakingThisInConstructor")
185
    public VCSGisWorkspaceImpl(JDBCServerExplorer wsexplorer, VCSGisCodeGenerator codeGenerator) {
186
        this.logger = new FilteredLogger(LOGGER, "VCSGisWorkspace", 100);
187
        this.logger.setInterval(10000);
188
        this.codeGenerator = codeGenerator;
189
        this.storesCache = new HashMap<>();
190
        this.wsexplorer = wsexplorer;
191
        this.workspaceEntitiesChangeListeners = ToolsSwingLocator.getToolsSwingManager().createChangeListenerHelper();
192
        this.repositoryEntitiesChangeListeners = ToolsSwingLocator.getToolsSwingManager().createChangeListenerHelper();
193
        this.userIdentificationRequester = null;
194

    
195
        VarsTable varsTable = new VarsTable();
196
        this.code = varsTable.get(this, "WORKSPACE_CODE");
197
        if (this.code == null) {
198
            throw new RuntimeException("Can't retrieve code from workspace '" + this.getMessageLabel() + "'");
199
        }
200
        this.currentUser = varsTable.get(this, "USER");
201
        this.authenticationToken = varsTable.get(this, "AUTHENTICATIONTOKEN");
202
        this.reloadWorkspaceEntities();
203
        this.repository = (VCSGisRepository) Json.toObject(varsTable.get(this, "REPOSITORY"));
204
        if (this.repository == null) {
205
            throw new RuntimeException("Can't retrieve repository from workspace '" + this.getMessageLabel() + "'");
206
        }
207
        this.label = varsTable.get(this, "WORKSPACE_LABEL");
208
//        LOGGER.debug("===: CREATE WORKSPACE "+ hexId(this)+ " (open code='"+this.code+"', label='"+this.label+"')");
209
    }
210

    
211
    private String getProviderName() {
212
        return this.wsexplorer.getProviderName();
213
    }
214

    
215
    public void initialize() throws Exception {
216
        DataManager dataManager = DALLocator.getDataManager();
217

    
218
//        List<VCSGisEntity> rentities = this.getRepositoryEntities();
219
//        if (!rentities.isEmpty()) {
220
//            JDBCStoreParameters storeParams = wsexplorer.get(EntitiesTable.TABLE_NAME);
221
//            FeatureStore storeEntities = (FeatureStore) dataManager.openStore(
222
//                    getProviderName(),
223
//                    storeParams
224
//            );
225
//            storeEntities.edit(FeatureStore.MODE_APPEND);
226
//            for (VCSGisEntity rentity : rentities) {
227
//                EntityRow entity = new EntityRow(this, storeEntities.createNewFeature());
228
//                entity.copyfrom(rentity);
229
//                entity.setLocalRevisionCode(null);
230
//                entity.insert(storeEntities);
231
//            }
232
//            storeEntities.finishEditing();
233
//        }
234
        VarsTable varsTable = new VarsTable();
235
        varsTable.set(this, "WORKSPACE_CODE", code);
236
        varsTable.set(this, "WORKSPACE_LABEL", label);
237
        varsTable.set(this, "REPOSITORY", repository.toJson().toString());
238
    }
239

    
240
    private String getMessageLabel() {
241
        return this.wsexplorer.getParameters().getUrl();
242
    }
243

    
244
    @Override
245
    public String getCode() {
246
        return this.code;
247
    }
248

    
249
    @Override
250
    public String getLabel() {
251
        return this.label;
252
    }
253

    
254
    @Override
255
    public void dispose() {
256
        for (Map.Entry<String, FeatureStore> entry : storesCache.entrySet()) {
257
            FeatureStore store = entry.getValue();
258
            if (store != null) {
259
                DisposeUtils.disposeQuietly(store);
260
            }
261
        }
262
        this.storesCache.clear();
263
        DisposeUtils.dispose(this.wsexplorer);
264
        this.wsexplorer = null;
265
        this.code = null;
266
    }
267

    
268
    @Override
269
    public JDBCServerExplorerParameters getExplorerParameters() {
270
        return this.wsexplorer.getParameters();
271
    }
272

    
273
    private boolean isInStoreIgnoreChanges(FeatureStore store) {
274
        if (this.storeIgnoreChanges == null) {
275
            return false;
276
        }
277
        return this.storeIgnoreChanges.contains(store);
278
    }
279

    
280
    private void addStoreIgnoreChanges(FeatureStore store) {
281
        if (this.storeIgnoreChanges == null) {
282
            this.storeIgnoreChanges = new HashSet<>();
283
        }
284
        this.storeIgnoreChanges.add(store);
285
    }
286

    
287
    private void removeStoreIgnoreChanges(FeatureStore store) {
288
        if (this.storeIgnoreChanges == null) {
289
            this.storeIgnoreChanges = new HashSet<>();
290
        }
291
        this.storeIgnoreChanges.remove(store);
292
    }
293

    
294
//    private boolean contains(FeatureStore store) {
295
//        return this.getEntity(store) != null;
296
//    }
297
//
298
//    private EntityRow getEntity(FeatureStore store) {
299
//        String s = (String) store.getProperty("VCSGIS_WORKSPACE");
300
//        if (s != null) {
301
//            if (StringUtils.equalsIgnoreCase(code, s)) {
302
//                return this.getWorkspaceEntityByName((String) store.getProperty("VCSGIS_ENTITY"));
303
//            }
304
//            return null;
305
//        }
306
//
307
//        DataStoreParameters params = store.getParameters();
308
//        if (!DataStore.H2SPATIAL_PROVIDER_NAME.equalsIgnoreCase(params.getProviderName())) {
309
//            store.setProperty("VCSGIS_WORKSPACE", "#########");
310
//            return null;
311
//        }
312
//
313
//        File targetFeature = ((HasAFile) params).getFile();
314
//        if (targetFeature == null) {
315
//            store.setProperty("VCSGIS_WORKSPACE", "#########");
316
//            return null;
317
//        }
318
//        EntityRow entity = this.getWorkspaceEntityByName(((JDBCStoreParameters) params).getTable());
319
//        if (entity == null) {
320
//            store.setProperty("VCSGIS_WORKSPACE", "#########");
321
//            return null;
322
//        }
323
//        store.setProperty("VCSGIS_WORKSPACE", this.code);
324
//        store.setProperty("VCSGIS_ENTITY", entity.getEntityName());
325
//
326
//        return entity;
327
//    }
328
    @Override
329
    public void reloadWorkspaceEntities() {
330
        FeatureStore store = null;
331
        try {
332
            Map<String, EntityRow> theEntitiesByName = new HashMap<>();
333
            Map<String, EntityRow> theEntitiesByCode = new HashMap<>();
334
            store = getFeatureStore(EntitiesTable.TABLE_NAME);
335
            for (Feature feature : store.getFeatureSet().iterable()) {
336
                EntityRow entity = new EntityRow(this, feature);
337
                theEntitiesByName.put(entity.getEntityName(), entity);
338
                theEntitiesByCode.put(entity.getCode(), entity);
339
                LOGGER.debug("===: loadEntities: " + entity.getEntityName() + " entity code " + entity.getEntityCode() + ", repo rev. " + entity.getRepositoryRevisionCode() + ", local rev. " + entity.getLocalRevisionCode());
340
            }
341
            this.workspaceEntitiesByName = theEntitiesByName;
342
            this.workspaceEntitiesByCode = theEntitiesByCode;
343
            this.workspaceEntitiesChangeListeners.fireEvent();
344

    
345
        } catch (Exception ex) {
346
            throw new VCSGisRuntimeException(ERR_CANT_RETRIEVE_ENTITIES, VCSGisUtils.getErrorMessage(ERR_CANT_RETRIEVE_ENTITIES));
347
        } finally {
348
            DisposeUtils.disposeQuietly(store);
349
        }
350
    }
351

    
352
    public ChangeListenerSupport getWorkspaceEntiesChangeListeners() {
353
        return this.workspaceEntitiesChangeListeners;
354
    }
355

    
356
    public ChangeListenerSupport getRepositoryEntiesChangeListeners() {
357
        return this.repositoryEntitiesChangeListeners;
358
    }
359

    
360
    @Override
361
    public List<VCSGisWorkspaceEntity> getWorkspaceEntities() {
362
        List<VCSGisWorkspaceEntity> entities = new ArrayList<>();
363
        entities.addAll(this.getEntitiesAsEntityRow());
364
        return entities;
365
    }
366

    
367
    private Collection<EntityRow> getEntitiesAsEntityRow() {
368
        if (this.workspaceEntitiesByName == null) {
369
            reloadWorkspaceEntities();
370
        }
371
        return this.workspaceEntitiesByName.values();
372
    }
373

    
374
    @Override
375
    public EntityRow getWorkspaceEntityByName(String name) {
376
        if (this.workspaceEntitiesByName == null) {
377
            this.reloadWorkspaceEntities();
378
        }
379
        return this.workspaceEntitiesByName.get(name);
380
    }
381

    
382
    @Override
383
    public EntityRow getWorkspaceEntityByCode(String code) {
384
        if (this.workspaceEntitiesByCode == null) {
385
            this.reloadWorkspaceEntities();
386
        }
387
        return this.workspaceEntitiesByCode.get(code);
388
    }
389

    
390
    @Override
391
    public boolean existsInWorkspace(String entity) {
392
        EntityRow lentity = this.getWorkspaceEntity(entity);
393
        return lentity!=null;
394
    }
395

    
396
    @Override
397
    public boolean existsInWorkspace(VCSGisEntity entity) {
398
        if( entity==null ) {
399
            return false;
400
        }
401
        return this.existsInWorkspace(entity.getEntityCode());
402
    }
403
    
404
    @Override
405
    public EntityRow getWorkspaceEntity(String entity) {
406
        EntityRow wsentity = this.getWorkspaceEntityByCode(entity);
407
        if (wsentity == null) {
408
            wsentity = this.getWorkspaceEntityByName(entity);
409
        }
410
        return wsentity;
411
    }
412

    
413
    @Override
414
    public VCSGisEntity getRepositoryEntityByCode(String entityCode) {
415
        if (this.repositoryEntitiesByCode == null) {
416
            reloadRepositoryEntities(null);
417
        }
418
        return this.repositoryEntitiesByCode.get(entityCode);
419
    }
420

    
421
    @Override
422
    public VCSGisEntity getRepositoryEntityByName(String entityName) {
423
        if (this.repositoryEntitiesByCode == null) {
424
            reloadRepositoryEntities(null);
425
        }
426
        for (VCSGisEntity entity : this.repositoryEntitiesByCode.values()) {
427
            if (StringUtils.equalsIgnoreCase(entity.getEntityName(), entityName)) {
428
                return entity;
429
            }
430
        }
431
        return null;
432
    }
433

    
434
    @Override
435
    public VCSGisEntity getEntity(String entityName) {
436
        VCSGisEntity entity = this.getWorkspaceEntity(entityName);
437
        if (entity == null) {
438
            entity = this.getRepositoryEntity(entityName);
439
        }
440
        return entity;
441
    }
442

    
443
    @Override
444
    public VCSGisEntity getRepositoryEntity(String entity) {
445
        VCSGisEntity rentity = this.getRepositoryEntityByCode(entity);
446
        if (rentity == null) {
447
            rentity = this.getRepositoryEntityByName(entity);
448
        }
449
        return rentity;
450
    }
451

    
452
    @Override
453
    public void forceReloadWorkspaceEntities() {
454
        this.workspaceEntitiesByCode = null;
455
        this.workspaceEntitiesByName = null;
456
    }
457

    
458
    @Override
459
    public void create_table(String name) {
460
        EntityRow entity = this.getWorkspaceEntityByName(name);
461
        if (entity == null) {
462
            throw new IllegalArgumentException("Can't locate informacion of table '" + name + "'.");
463
        }
464
        create_table(entity);
465
    }
466

    
467
    @Override
468
    public void create_table(VCSGisEntity entity) {
469
        create_table(entity, entity.getEntityName());
470
    }
471
    
472
    public void create_table(VCSGisEntity entity, String tableName) {
473
        if (entity == null) {
474
            throw new IllegalArgumentException("Entity is null.");
475
        }
476
        try {
477
//            DataManager dataManager = DALLocator.getDataManager();
478
            JDBCNewStoreParameters addparams = (JDBCNewStoreParameters) this.wsexplorer.getAddParameters(tableName);
479
            addparams.setDefaultFeatureType(entity.getFeatureType());
480
            this.wsexplorer.add(getProviderName(), addparams, true);
481

    
482
        } catch (Exception ex) {
483
            throw new RuntimeException("Can't create table '" + entity.getEntityName() + "'.", ex);
484
        }
485

    
486
    }
487

    
488
    @Override
489
    public FeatureType getFeatureType(String tableName) {
490
        EntityRow entity = null;
491
        if (!INTERNAL_WORKSPACE_TABLES.contains(tableName)) {
492
            entity = this.getWorkspaceEntityByName(tableName);
493
            if (entity == null) {
494
                return null;
495
            }
496
            return entity.getFeatureType();
497
        }
498
        FeatureType ft = null;
499
        try {
500
            FeatureStore store = this.storesCache.get(tableName);
501
            if (store != null) {
502
                ft = store.getDefaultFeatureType();
503
            } else {
504
                DataManager dataManager = DALLocator.getDataManager();
505
                JDBCStoreParameters params = this.wsexplorer.get(tableName);
506
                store = (FeatureStore) dataManager.openStore(
507
                        getProviderName(),
508
                        params
509
                );
510
                this.storesCache.put(tableName, store);
511
                ft = store.getDefaultFeatureType();
512
            }
513
            return ft;
514
        } catch (Exception ex) {
515
            String msg = "can't open store from '" + this.getMessageLabel() + "'.";
516
            throw new RuntimeException(msg, ex);
517
        }
518
    }
519

    
520
    @Override
521
    public FeatureStore getFeatureStore(String tableName) {
522
        EntityRow entity = null;
523
        if (!INTERNAL_WORKSPACE_TABLES.contains(tableName)) {
524
            entity = this.getWorkspaceEntityByName(tableName);
525
            if (entity == null) {
526
                return null;
527
            }
528
            return getFeatureStore(entity);
529
        }
530
        FeatureStore store = this.storesCache.get(tableName);
531
        if (store != null) {
532
            DisposeUtils.bind(store);
533
            return store;
534
        }
535
        DataManager dataManager = DALLocator.getDataManager();
536
        try {
537
            JDBCStoreParameters params = this.wsexplorer.get(tableName);
538
            store = (FeatureStore) dataManager.openStore(
539
                    getProviderName(),
540
                    params
541
            );
542
            this.storesCache.put(tableName, store);
543
            DisposeUtils.bind(store);
544
            return store;
545
        } catch (Exception ex) {
546
            LOGGER.trace("can't open store from '" + this.getMessageLabel() + "'.", ex);
547
            return null;
548
//            String msg = "can't open store from '" + this.getMessageLabel() + "'.";
549
//            throw new RuntimeException(msg, ex);
550
        }
551
    }
552

    
553
    private FeatureStore getFeatureStore(VCSGisEntity entity) {
554
        FeatureStore store = this.storesCache.get(entity.getEntityName());
555
        if (store != null) {
556
            DisposeUtils.bind(store);
557
            return store;
558
        }
559
        DataManager dataManager = DALLocator.getDataManager();
560
        try {
561
            JDBCStoreParameters params = this.wsexplorer.get(entity.getEntityName());
562
            store = (FeatureStore) dataManager.openStore(
563
                    getProviderName(),
564
                    params
565
            );
566
            StoreProperties.set(store, this, entity.getEntityName());
567
            this.storesCache.put(entity.getEntityName(), store);
568
            DisposeUtils.bind(store);
569
            return store;
570
        } catch (Exception ex) {
571
            LOGGER.trace("can't open store from '" + this.getMessageLabel() + "'.", ex);
572
            return null;
573
//            String msg = "can't open store from '" + this.getMessageLabel() + "'.";
574
//            throw new RuntimeException(msg, ex);
575
        }
576
    }
577

    
578
    public FeatureStore openFeatureStore(VCSGisEntity entity) {
579
        DataManager dataManager = DALLocator.getDataManager();
580
        try {
581
            JDBCStoreParameters params = this.wsexplorer.get(entity.getEntityName());
582
            FeatureStore store = (FeatureStore) dataManager.openStore(
583
                    getProviderName(),
584
                    params
585
            );
586
            return store;
587
        } catch (Exception ex) {
588
            LOGGER.trace("can't open store from '" + this.getMessageLabel() + "'.", ex);
589
            return null;
590
        }
591
    }
592

    
593
    @Override
594
    public FeatureStore openFeatureStore(String tableName) {
595
        DataManager dataManager = DALLocator.getDataManager();
596
        try {
597
            JDBCStoreParameters params = this.wsexplorer.get(tableName);
598
            FeatureStore store = (FeatureStore) dataManager.openStore(
599
                    getProviderName(),
600
                    params
601
            );
602

    
603
            return store;
604
        } catch (Exception ex) {
605
            LOGGER.trace("can't open store from '" + this.getMessageLabel() + "'.", ex);
606
            return null;
607
        }
608
    }
609

    
610
    @Override
611
    public String createUniqueCode() {
612
        return this.codeGenerator.generateCode();
613
    }
614

    
615
    @Override
616
    public String getErrorMessage(int errcode) {
617
        return VCSGisUtils.getErrorMessage(errcode);
618
    }
619

    
620
    @Override
621
    public int addChange(int operation, FeatureStore userStore, Feature feature) {
622
        String entityName = StoreProperties.getEntityName(userStore);
623
        if (StringUtils.isBlank(entityName)) {
624
            return ERR_STORE_NOT_IN_VERSION_CONTROL;
625
        }
626
        if (this.isInStoreIgnoreChanges(userStore)) {
627
            LOGGER.debug("===: ADD_CHANGE: Skip (" + userStore.getName() + ")");
628
            return ERR_NO_ERROR;
629
        }
630
        EntityRow entity = this.getWorkspaceEntityByName(entityName);
631
        FeatureStore changesStore = this.getFeatureStore(WorkspaceChangesTable.TABLE_NAME);
632
        try {
633
            changesStore.edit(MODE_PASS_THROUGH);
634
            return addChange(entity, operation, changesStore, feature, userStore.getOriginalFeature(feature));
635
        } catch (Exception ex) {
636
            LOGGER.warn("Can't add change (op " + VCSGisUtils.getOperationLabel(operation) + ", " + entity.getEntityName() + ")", ex);
637
            changesStore.cancelEditingQuietly();
638
            return ERR_CANT_ADD_CHANGE;
639
        } finally {
640
            changesStore.finishEditingQuietly();
641
            DisposeUtils.dispose(changesStore);
642
        }
643
    }
644

    
645
    private int addChange(VCSGisWorkspaceEntity entity, int operation, FeatureStore changesStore, Feature feature, Feature oldFeature) {
646
        try {
647
            String featureCode = feature.getString(entity.getFeatureIdFieldName());
648
            Feature previousChange = changesStore.findFirst(WorkspaceChangesTable.FEATUREID + " = '" + featureCode + "'"); // and " + WorkspaceChangesTable.OPERATION+ " = " + operation);
649
            if (previousChange != null) {
650
                int previousOperation = previousChange.getInt(WorkspaceChangesTable.OPERATION);
651
                /*
652
                operation - previo
653
                INS - INS -> Error
654
                INS - UPD -> Error
655
                INS - DEL -> Error
656
                UPD - INS -> no hace nada y sale con OK
657
                UPD - UPD -> no hace nada y sale con OK
658
                UPD - DEL -> Error
659
                 */
660
                switch (operation) {
661
                    case OP_INSERT:
662
                        return ERR_CANT_ADD_CHANGE;
663
                    case OP_UPDATE:
664
                        switch (previousOperation) {
665
                            case OP_INSERT:
666
                            case OP_UPDATE:
667
                                return ERR_OK;
668
                            case OP_DELETE:
669
                                return ERR_CANT_ADD_CHANGE;
670
                            default:
671
                                return ERR_OK;
672
                        }
673

    
674
                }
675

    
676
                return ERR_OK;
677
            }
678

    
679
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, changesStore.createNewFeature());
680
            change.newCode();
681
            change.setEntityCode(entity.getEntityCode());
682
            change.setFeatureCode(featureCode);
683
            change.setOperation(operation);
684
            change.setLabel(feature.getString(entity.getFieldForLabel()));
685
            if(oldFeature != null){
686
                change.setData(oldFeature.toJson().toString());
687
            }
688
            change.setSelected(true);
689
            switch (operation) {
690
                case OP_INSERT:
691
                    change.setStatus(STATE_LOCAL_NEW);
692
                    break;
693
                case OP_UPDATE:
694
                    change.setStatus(STATE_LOCAL_MODIFIED);
695
                    break;
696
            }
697

    
698
            change.insert(changesStore);
699
            return ERR_OK;
700
        } catch (Exception ex) {
701
            LOGGER.warn("Can't add change (op " + VCSGisUtils.getOperationLabel(operation) + ", " + entity.getEntityName() + ")", ex);
702
            return ERR_CANT_ADD_CHANGE;
703
        }
704
    }
705

    
706
    private int addDeleteChange(VCSGisWorkspaceEntity entity, FeatureStore changesStore, String featureCode, String label, Feature oldFeature) {
707
        try {
708
            WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
709
            WorkspaceChangeRow previousChange = changesTable.find(this, changesStore, entity.getEntityCode(), featureCode);
710
            if (previousChange != null) {
711
                
712
                /*
713
                DEL - INS -> Quitar el insert y salir con OK
714
                DEL - UPD -> Quitar el update y meter delete (continuar)
715
                DEL - DEL -> Error
716
                 */
717
                switch (previousChange.getOperation()) {
718
                    case OP_INSERT:
719
                        previousChange.delete(changesStore);
720
                        return ERR_OK;
721
                    case OP_UPDATE:
722
                    default:
723
                        previousChange.setOperation(OP_DELETE);
724
                        previousChange.setSelected(true);
725
                        previousChange.update();
726
                        break;
727

    
728
                    case OP_DELETE:
729
                        return ERR_CANT_ADD_CHANGE;
730
                }
731
            }
732

    
733
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, changesStore.createNewFeature());
734
            change.newCode();
735
            change.setEntityCode(entity.getEntityCode());
736
            change.setFeatureCode(featureCode);
737
            change.setOperation(OP_DELETE);
738
            change.setLabel(label);
739
            if(oldFeature != null){
740
                change.setData(oldFeature.toJson().toString());
741
            }
742
            change.setSelected(true);
743
            change.setStatus(STATE_LOCAL_MODIFIED);
744
            change.insert(changesStore);
745
            return ERR_OK;
746
        } catch (Exception ex) {
747
            LOGGER.warn("Can't add delete change (" + entity.getEntityName() + ")", ex);
748
            return ERR_CANT_ADD_CHANGE;
749
        }
750
    }
751

    
752
    @Override
753
    public int addEntity(FeatureType featureType, String name, String description, String fieldForLabel) {
754
        return this.addEntity(featureType, name, description, fieldForLabel, null, null, null);
755
    }
756

    
757
    @Override
758
    public int addEntity(FeatureType featureType, String name, String description, String fieldForLabel, String category, String label, String pkName) {
759
        FeatureStore store = null;
760
        int err = ERR_NO_ERROR;
761
        try {
762
            LOGGER.debug("===: ADD_ENTITY " + this.getCode() + ", '" + this.getLabel() + "', " + name);
763
            EditableFeatureType ft = featureType.getCopy().getEditable();
764

    
765
            for (FeatureAttributeDescriptor attr : ft.getPrimaryKey()) {
766
                EditableFeatureAttributeDescriptor editAttr = (EditableFeatureAttributeDescriptor) attr;
767
                editAttr.setIsPrimaryKey(false);
768
                editAttr.setAllowNull(false);
769
                editAttr.setIsIndexed(true);
770
                editAttr.setAllowIndexDuplicateds(false);
771
            }
772

    
773
            EditableFeatureAttributeDescriptor attr = (EditableFeatureAttributeDescriptor) ft.getAttributeDescriptor(FEATURECODE_FIELD_NAME);
774
            if (attr == null) {
775
                err = ERR_ENTITY_NOT_HAS_VCSGISCODE;
776
                ft.add(FEATURECODE_FIELD_NAME, DataTypes.STRING)
777
                        .setSize(40)
778
                        .setIsPrimaryKey(true)
779
                        .setIsIndexed(true)
780
                        .setAllowIndexDuplicateds(false)
781
                        .setLabel("VCSGIS Code");
782
                ft.setHasOID(false);
783
            } else {
784
                if (!attr.isPrimaryKey()) {
785
                    attr.setIsPrimaryKey(true);
786
                    ft.setHasOID(false);
787
                }
788
            }
789

    
790
            EditableFeatureAttributeDescriptor geomattr = (EditableFeatureAttributeDescriptor) ft.getDefaultGeometryAttribute();
791
            if( geomattr!=null ) {
792
                geomattr.setIsIndexed(true);
793
            }
794

    
795
            featureType = ft.getNotEditableCopy();
796
            if (featureType.getAttributeDescriptor(fieldForLabel) == null) {
797
                FeatureAttributeDescriptor[] pk = featureType.getPrimaryKey();
798
                if (pk == null || pk.length < 1) {
799
                    fieldForLabel = featureType.getAttributeName(0);
800
                } else {
801
                    fieldForLabel = pk[0].getName();
802
                }
803
            }
804

    
805
            err = ERR_CANT_OPEN_ENTITIES;
806
            EntityRow entity = new EntityRow(this);
807
            entity.newCode();
808
            entity.setEntityName(name);
809
            entity.setDataTableName(DEFAULT_DATA_TABLE);
810
            entity.setFeatureIdFieldName(FEATURECODE_FIELD_NAME);
811
            entity.setGeometryFieldName(featureType.getDefaultGeometryAttributeName());
812
            entity.setDescription(description);
813
            entity.setFieldForLabel(fieldForLabel);
814
            entity.setFeatureTypeAsJson(featureType.toJsonBuilder().toString());
815
            entity.setLocalRevisionCode(null);
816
            entity.setRepositoryRevisionCode(null);
817
            entity.setCategory(category);
818
            entity.setLabel(label);
819
            entity.setState(STATE_LOCAL_NEW);
820
            entity.insert();
821

    
822
            this.forceReloadWorkspaceEntities();
823
            err = ERR_CANT_INSERT_CHANGE;
824

    
825
            entity = this.getWorkspaceEntityByName(name);
826
            FeatureStore changesStore = this.getFeatureStore(WorkspaceChangesTable.TABLE_NAME);
827
//            addChange(entity, OP_ADD_ENTITY, changesStore, null, null);
828

    
829
            WorkspaceChangeRow change = new WorkspaceChangeRow(this);
830
            change.newCode();
831
            change.setEntityCode(entity.getCode());
832
            change.setFeatureCode(null);
833
            change.setOperation(OP_ADD_ENTITY);
834
            change.setSelected(true);
835
            change.insert();
836

    
837
            this.create_table(entity);
838

    
839
        } catch (VCSGisRuntimeException ex) {
840
            LOGGER.warn("can't add entity '" + name + "'.", ex);
841
            if (store != null) {
842
                store.cancelEditingQuietly();
843
            }
844
            return ex.getErrnum();
845
        } catch (Exception ex) {
846
            LOGGER.warn("can't add entity '" + name + "'.", ex);
847
            if (store != null) {
848
                store.cancelEditingQuietly();
849
            }
850
            return err;
851
        } finally {
852
            DisposeUtils.disposeQuietly(store);
853
        }
854
        return ERR_NO_ERROR;
855
    }
856

    
857
    @Override
858
    public int addChanges(FeatureStore store, Iterator<Feature> insertedsFeatures, Iterator<Feature> updatedsFeatures, Iterator<FeatureReference> deletedsFeatures) {
859
        String entityName = StoreProperties.getEntityName(store);
860
        if (StringUtils.isBlank(entityName)) {
861
            return ERR_STORE_NOT_IN_VERSION_CONTROL;
862
        }
863
        if (this.isInStoreIgnoreChanges(store)) {
864
            LOGGER.debug("===: ADD_CHANGE: Skip (" + store.getName() + ")");
865
            return ERR_NO_ERROR;
866
        }
867
        EntityRow entity = this.getWorkspaceEntityByName(entityName);
868
        if (entity == null) {
869
            return ERR_STORE_NOT_IN_VERSION_CONTROL;
870
        }
871
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
872
        FeatureStore workspaceChangesStore = null;
873
        int err = ERR_CANT_OPEN_CHANGES;
874
        try {
875
            workspaceChangesStore = this.getFeatureStore(WorkspaceChangesTable.TABLE_NAME);
876
            err = ERR_CANT_INSERT_CHANGE;
877
            workspaceChangesStore.edit(FeatureStore.MODE_PASS_THROUGH);
878
            if (insertedsFeatures != null) {
879
                while (insertedsFeatures.hasNext()) {
880
                    Feature f = insertedsFeatures.next();
881
                    if (f == null) {
882
                        continue;
883
                    }
884
                    addChange(entity, OP_INSERT, workspaceChangesStore, f, null);
885
                    
886
//                    WorkspaceChangeRow change = new WorkspaceChangeRow(this);
887
//                    change.newCode();
888
//                    change.setEntityCode(entity.getCode());
889
//                    change.setFeatureCode(f.getString(entity.getFeatureIdFieldName()));
890
//                    change.setOperation(OP_INSERT);
891
//                    change.setLabel(f.getString(entity.getFieldForLabel()));
892
//                    change.setSelected(true);
893
//                    change.insert(workspaceChangesStore);
894
                }
895
            }
896
            if (updatedsFeatures != null) {
897
                while (updatedsFeatures.hasNext()) {
898
                    Feature f = updatedsFeatures.next();
899
                    if (f == null) {
900
                        continue;
901
                    }
902
                    
903
                    addChange(entity, OP_UPDATE, workspaceChangesStore, f, store.getOriginalFeature(f));
904
                    
905
//                    WorkspaceChangeRow change = new WorkspaceChangeRow(this);
906
//                    String featureCode = f.getString(entity.getFeatureIdFieldName());
907
//                    WorkspaceChangeRow previousChange = changesTable.find(this, workspaceChangesStore, entity.getCode(), featureCode);
908
//                    if (previousChange == null) {
909
//
910
//                        change.newCode();
911
//                        change.setEntityCode(entity.getCode());
912
//                        change.setFeatureCode(f.getString(entity.getFeatureIdFieldName()));
913
//                        change.setOperation(OP_UPDATE);
914
//                        change.setLabel(f.getString(entity.getFieldForLabel()));
915
//                        change.setSelected(true);
916
//                        change.insert(workspaceChangesStore);
917
//                    }
918
                }
919
            }
920
            if (deletedsFeatures != null) {
921
                while (deletedsFeatures.hasNext()) {
922
                    FeatureReference fr = deletedsFeatures.next();
923
                    if (fr == null) {
924
                        continue;
925
                    }
926
                    Feature f = fr.getFeatureQuietly();
927
                    if (f == null) {
928
                        continue;
929
                    }
930
                    
931
                    addDeleteChange(entity, workspaceChangesStore, f.getString(entity.getFeatureIdFieldName()), f.getString(entity.getFieldForLabel()), store.getOriginalFeature(f));
932
//                    WorkspaceChangeRow change = new WorkspaceChangeRow(this);
933
//                    String featureCode = f.getString(entity.getFeatureIdFieldName());
934
//                    WorkspaceChangeRow previousChange = changesTable.find(this, workspaceChangesStore, entity.getCode(), featureCode);
935
//                    if (previousChange == null) {
936
//                        change.newCode();
937
//                        change.setEntityCode(entity.getCode());
938
//                        change.setFeatureCode(f.getString(entity.getFeatureIdFieldName()));
939
//                        change.setOperation(OP_DELETE);
940
//                        change.setLabel(f.getString(entity.getFieldForLabel()));
941
//                        change.setSelected(true);
942
//                        change.insert(workspaceChangesStore);
943
//                    } else {
944
//                        switch (previousChange.getOperation()) {
945
//                            case OP_INSERT:
946
//                                previousChange.delete(workspaceChangesStore);
947
//                                break;
948
//                            case OP_DELETE:
949
//                                LOGGER.warn("Try delete feature already deleted (.'" + previousChange.getRelatedFeature().toJson().toString() + "'");
950
//                                break;
951
//                            case OP_UPDATE:
952
//                                previousChange.setOperation(OP_DELETE);
953
//                                previousChange.setSelected(true);
954
//                                previousChange.update();
955
//                                break;
956
//                        }
957
//                    }
958
                }
959
            }
960
            workspaceChangesStore.finishEditing();
961
            err = ERR_NO_ERROR;
962
        } catch (Exception ex) {
963
            this.logger.warn("Can't add changes.", ex);
964
            if (workspaceChangesStore != null) {
965
                workspaceChangesStore.cancelEditingQuietly();
966
            }
967
        } finally {
968
            DisposeUtils.disposeQuietly(workspaceChangesStore);
969
        }
970
        return err;
971
    }
972

    
973
    @Override
974
    public int add(String name, FeatureStore source, String fieldForLabel) {
975
        return this.add(name, source, fieldForLabel, null, null, null, null);
976
    }
977

    
978
    @Override
979
    public int add(String name, FeatureStore source, String fieldForLabel, String category, String label) {
980
        return this.add(name, source, fieldForLabel, category, label, null, null);
981
    }
982

    
983
    @Override
984
    public int add(String name, FeatureStore source, String fieldForLabel, String category, String label, String pkName, SimpleTaskStatus status) {
985
        if (isInMyDatabase(source)) {
986
            return addExistingTable(name, source, fieldForLabel, category, label, pkName, status);
987
        } else {
988
            return addNewTable(name, source, fieldForLabel, category, label, pkName, status);
989
        }
990

    
991
    }
992

    
993
    private int addNewTable(String name, FeatureStore source, String fieldForLabel, String category, String label, String pkName, SimpleTaskStatus status) {
994
        if (this.getEntity(name) != null) { // is in VCS
995
            return ERR_ENTITY_ALREADY_EXISTS;
996
        }
997
        I18nManager i18n = ToolsLocator.getI18nManager();
998
        if (status == null) {
999
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(i18n.getTranslation("_Add_layer"));
1000
            status.setAutoremove(true);
1001
            status.add();
1002
        }
1003

    
1004
        FeatureStore target = null;
1005
        FeatureSet srcFeatures = null;
1006
        int errcode = ERR_NO_ERROR;
1007
        DataTransaction transaction = null;
1008
        try {
1009
            transaction = DALLocator.getDataManager().createTransaction();
1010
            transaction.begin();
1011
            LOGGER.debug("===: ADD " + this.getCode() + ", '" + this.getLabel() + "', " + name);
1012
            EntityRow entity = this.getWorkspaceEntityByName(name);
1013
            if (entity != null) {
1014
                return ERR_ENTITY_ALREADY_EXISTS;
1015
            }
1016
            status.message(i18n.getTranslation("_Adding_table_layer"));
1017
            FeatureType ft = source.getDefaultFeatureTypeQuietly();
1018
            errcode = this.addEntity(ft, name, null, fieldForLabel, category, label, pkName);
1019
            if (errcode != ERR_NO_ERROR) {
1020
                transaction.rollbackQuietly();
1021
                return errcode;
1022
            }
1023
            errcode = ERR_CANT_OPEN_STORE;
1024
            target = this.openFeatureStore(name);
1025
            transaction.add(target);
1026
            errcode = ERR_CANT_RETRIEVE_SOURCE_FEATURES;
1027
            status.message(i18n.getTranslation("_Preparing_source"));
1028
            srcFeatures = source.getFeatureSet();
1029
            transaction.add(srcFeatures);
1030
            errcode = ERR_CANT_INSERT_FEATURES;
1031
            target.edit(MODE_APPEND);
1032

    
1033
            FeatureStore changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
1034
            transaction.add(changesStore);
1035
            changesStore.edit(MODE_APPEND);
1036

    
1037
            this.addStoreIgnoreChanges(target);
1038
            entity = this.getWorkspaceEntityByName(name);
1039

    
1040
            status.message(null);
1041
            status.setRangeOfValues(0, srcFeatures.size64());
1042
            status.setCurValue(0);
1043
            for (Feature srcFeature : srcFeatures) {
1044
                EditableFeature targetFeature;
1045
                String featureCode = this.createUniqueCode();
1046
                targetFeature = target.createNewFeature(srcFeature);
1047
                targetFeature.set(FEATURECODE_FIELD_NAME, featureCode);
1048
                target.insert(targetFeature);
1049

    
1050
                WorkspaceChangeRow change = new WorkspaceChangeRow(this);
1051
                change.newCode();
1052
                change.setEntityCode(entity.getEntityCode());
1053
                change.setFeatureCode(featureCode);
1054
                change.setOperation(OP_INSERT);
1055
                change.setLabel(targetFeature.getString(entity.getFieldForLabel()));
1056
                change.setSelected(true);
1057
                change.setStatus(STATE_LOCAL_NEW);
1058
                change.insert(changesStore);
1059

    
1060
                status.incrementCurrentValue();
1061
                if (status.isCancellationRequested()) {
1062
                    transaction.rollbackQuietly();
1063
                    status.cancel();
1064
                    return ERR_CANCELLED_BY_USER;
1065
                }
1066
            }
1067
            status.message(i18n.getTranslation("_Finishing"));
1068
            target.finishEditing();
1069
            transaction.commit();
1070
            status.terminate();
1071
            return ERR_NO_ERROR;
1072
        } catch (Exception ex) {
1073
            LOGGER.warn("Can't add features to '" + name + "' in '" + this.getMessageLabel() + "'.", ex);
1074
            status.abort();
1075
            DataTransaction.rollbackQuietly(transaction);
1076
            return errcode;
1077
        } finally {
1078
            DisposeUtils.disposeQuietly(transaction);
1079
        }
1080
    }
1081

    
1082
    private int addExistingTable(String name, FeatureStore source, String fieldForLabel, String category, String label, String pkName, SimpleTaskStatus status) {
1083
        if (this.getEntity(name) != null) { // is in VCS
1084
            return ERR_ENTITY_ALREADY_EXISTS;
1085
        }
1086
        DataManager dataManager = DALLocator.getDataManager();
1087
        I18nManager i18n = ToolsLocator.getI18nManager();
1088
        if (status == null) {
1089
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(i18n.getTranslation("_Add_layer"));
1090
            status.setAutoremove(true);
1091
            status.add();
1092
        }
1093

    
1094
        FeatureStore target = null;
1095
        FeatureSet targetFeatures = null;
1096
        int errcode = ERR_NO_ERROR;
1097
        DataTransaction transaction = null;
1098
        try {
1099
            JDBCServerExplorer explorer = (JDBCServerExplorer) dataManager.openServerExplorer(this.getProviderName(), this.getExplorerParameters());
1100
            transaction = dataManager.createTransaction();
1101
            transaction.begin();
1102
            transaction.add(explorer);
1103
            LOGGER.debug("===: ADD " + this.getCode() + ", '" + this.getLabel() + "', " + name);
1104
            EntityRow entity = this.getWorkspaceEntityByName(name);
1105
            if (entity != null) {
1106
                return ERR_ENTITY_ALREADY_EXISTS;
1107
            }
1108
            status.message(i18n.getTranslation("_Adding_table_layer"));
1109

    
1110
            FeatureType featureType = source.getDefaultFeatureType();
1111
            FeatureAttributeDescriptor attr = featureType.getAttributeDescriptor(FEATURECODE_FIELD_NAME);
1112
            if (attr == null) {
1113
//                explorer.execute("ALTER TABLE \""+name+"\" ADD COLUMN \""+FEATURECODE_FIELD_NAME+"\" VARCHAR(40)");
1114
                explorer.execute(
1115
                        String.format(
1116
                                VCSGisUtils.getSqlTemplate(explorer.getProviderName(), "alterTableAddColumnVCSGISCODE"),
1117
                                name
1118
                        )
1119
                );
1120
            }
1121

    
1122
            ResourcesStorage resourcesStorage = source.getResourcesStorage();
1123
            if (resourcesStorage != null) {
1124
                Resource resource = resourcesStorage.getResource("dal");
1125
                if (resource != null) {
1126
                    resourcesStorage.remove(resource.getName());
1127
                }
1128
            }
1129

    
1130
            target = (FeatureStore) dataManager.openStore(source.getProviderName(), source.getParameters());
1131

    
1132
            transaction.add(target);
1133
            errcode = ERR_CANT_RETRIEVE_SOURCE_FEATURES;
1134
            status.message(i18n.getTranslation("_Preparing_source"));
1135
            targetFeatures = target.getFeatureSet();
1136
            transaction.add(targetFeatures);
1137
            errcode = ERR_CANT_INSERT_FEATURES;
1138
            target.edit(MODE_PASS_THROUGH);
1139

    
1140
            FeatureStore changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
1141
            transaction.add(changesStore);
1142
            changesStore.edit(MODE_APPEND);
1143

    
1144
            FeatureStore entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1145
            transaction.add(entitiesStore);
1146
            entitiesStore.edit(MODE_FULLEDIT);
1147

    
1148
            this.addStoreIgnoreChanges(target);
1149
//            entity = this.getWorkspaceEntityByName(name);
1150
            errcode = ERR_CANT_OPEN_ENTITIES;
1151
            entity = new EntityRow(this);
1152
            entity.newCode();
1153
            entity.setEntityName(name);
1154
            entity.setDataTableName(DEFAULT_DATA_TABLE);
1155
            entity.setFeatureIdFieldName(FEATURECODE_FIELD_NAME);
1156
            entity.setGeometryFieldName(featureType.getDefaultGeometryAttributeName());
1157
            entity.setDescription(null);
1158
            entity.setFieldForLabel(fieldForLabel);
1159
            entity.setFeatureTypeAsJson(featureType.toJsonBuilder().toString());
1160
            entity.setLocalRevisionCode(null);
1161
            entity.setRepositoryRevisionCode(null);
1162
            entity.setState(STATE_LOCAL_NEW);
1163
            entity.setCategory(category);
1164
            entity.setLabel(label);
1165
            entity.insert(entitiesStore);
1166
            entitiesStore.finishEditing();
1167

    
1168
            this.forceReloadWorkspaceEntities();
1169
            errcode = ERR_CANT_INSERT_CHANGE;
1170

    
1171
            entity = this.getWorkspaceEntityByName(name);
1172

    
1173
//            addChange(entity, OP_ADD_ENTITY, changesStore, null, null);
1174
            WorkspaceChangeRow change = new WorkspaceChangeRow(this);
1175
            change.newCode();
1176
            change.setEntityCode(entity.getCode());
1177
            change.setFeatureCode(null);
1178
            change.setOperation(OP_ADD_ENTITY);
1179
            change.setSelected(true);
1180
            change.insert(changesStore);
1181

    
1182
            status.message(null);
1183
            status.setRangeOfValues(0, targetFeatures.size64());
1184
            status.setCurValue(0);
1185
            for (Feature targetFeature : targetFeatures) {
1186
                EditableFeature editableFeature;
1187
                String featureCode = this.createUniqueCode();
1188

    
1189
                editableFeature = targetFeature.getEditable();
1190
                editableFeature.set(FEATURECODE_FIELD_NAME, featureCode);
1191
                targetFeatures.update(editableFeature);
1192

    
1193
                change = new WorkspaceChangeRow(this);
1194
                change.newCode();
1195
                change.setEntityCode(entity.getEntityCode());
1196
                change.setFeatureCode(featureCode);
1197
                change.setOperation(OP_INSERT);
1198
                change.setLabel(editableFeature.getString(entity.getFieldForLabel()));
1199
                change.setSelected(true);
1200
                change.setStatus(STATE_LOCAL_NEW);
1201
                change.insert(changesStore);
1202

    
1203
                status.incrementCurrentValue();
1204
                if (status.isCancellationRequested()) {
1205
                    transaction.rollbackQuietly();
1206
                    status.cancel();
1207
                    return ERR_CANCELLED_BY_USER;
1208
                }
1209
            }
1210

    
1211
            target.finishEditing();
1212

    
1213
//            explorer.execute("ALTER TABLE \""+name+"\" DROP PRIMARY KEY");
1214
            explorer.execute(
1215
                    String.format(
1216
                            VCSGisUtils.getSqlTemplate(explorer.getProviderName(), "alterTableDropPrimaryKey"),
1217
                            entity.getEntityName()
1218
                    )
1219
            );
1220

    
1221
//            explorer.execute("ALTER TABLE \""+name+"\" ALTER COLUMN \""+FEATURECODE_FIELD_NAME+"\" SET NOT NULL");
1222
            explorer.execute(
1223
                    String.format(
1224
                            VCSGisUtils.getSqlTemplate(explorer.getProviderName(), "alterTableAlterColumnVCSGISCODESetNotNull"),
1225
                            entity.getEntityName()
1226
                    )
1227
            );
1228

    
1229
//            explorer.execute("ALTER TABLE \""+name+"\" ADD PRIMARY KEY (\""+FEATURECODE_FIELD_NAME+"\")");
1230
            explorer.execute(
1231
                    String.format(
1232
                            VCSGisUtils.getSqlTemplate(explorer.getProviderName(), "alterTableAddPrimaryKeyVCSGISCODE"),
1233
                            entity.getEntityName()
1234
                    )
1235
            );
1236

    
1237
            target = (FeatureStore) dataManager.openStore(source.getProviderName(), source.getParameters());
1238

    
1239
            EditableFeatureType ft = target.getDefaultFeatureTypeQuietly().getEditable();
1240
            EditableFeatureAttributeDescriptor geomattr = (EditableFeatureAttributeDescriptor) ft.getDefaultGeometryAttribute();
1241
            if( geomattr!=null ) {
1242
                geomattr.setIsIndexed(true);
1243
            }
1244

    
1245
            entitiesStore.edit(MODE_FULLEDIT);
1246

    
1247
            entity.setFeatureTypeAsJson(ft.toJsonBuilder().toString());
1248
            entity.update(entitiesStore);
1249

    
1250
            entitiesStore.finishEditing();
1251

    
1252
            status.message(i18n.getTranslation("_Finishing"));
1253
            transaction.commit();
1254
            status.terminate();
1255
            return ERR_NO_ERROR;
1256
        } catch (Exception ex) {
1257
            LOGGER.warn("Can't add features to '" + name + "' in '" + this.getMessageLabel() + "'.", ex);
1258
            status.abort();
1259
            DataTransaction.rollbackQuietly(transaction);
1260
            return errcode;
1261
        } finally {
1262
            DisposeUtils.disposeQuietly(transaction);
1263
        }
1264
    }
1265

    
1266
    @Override
1267
    public VCSGisWorkspaceChanges<VCSGisWorkspaceChange> getLocalChanges() {
1268
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1269
        ChangesImpl changes = new ChangesImpl<WorkspaceChangeRow>(changesTable.getByEntityCode(this, null), WorkspaceChangesTable.SELECTED) {
1270
            @Override
1271
            protected WorkspaceChangeRow createChange(Feature f) {
1272
                return new WorkspaceChangeRow(VCSGisWorkspaceImpl.this, f);
1273
            }
1274

    
1275
            @Override
1276
            protected void updateChange(FeatureStore store, WorkspaceChangeRow change) {
1277
                change.update(store);
1278
            }
1279

    
1280
        };
1281
        return changes;
1282
    }
1283

    
1284
//    @Override
1285
//    public VCSGisWorkspaceChanges<VCSGisWorkspaceChange> getLocalChangesByEntityCodeOrName(String codeOrName) {
1286
//        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1287
//        ChangesImpl changes = new ChangesImpl<WorkspaceChangeRow>(changesTable.getByEntityCode(this, codeOrName), WorkspaceChangesTable.SELECTED) {
1288
//            @Override
1289
//            protected WorkspaceChangeRow createChange(Feature f) {
1290
//                return new WorkspaceChangeRow(VCSGisWorkspaceImpl.this, f);
1291
//            }
1292
//
1293
//            @Override
1294
//            protected void updateChange(FeatureStore store, WorkspaceChangeRow change) {
1295
//                change.update(store);
1296
//            }
1297
//
1298
//        };
1299
//        return changes;
1300
//    }
1301

    
1302
//    @Override
1303
//    public VCSGisWorkspaceChanges<VCSGisWorkspaceChange> getLocalChangesByEntityName(String entityName) {
1304
//        EntityRow entity = this.getWorkspaceEntityByName(entityName);
1305
//        return getLocalChangesByEntityCode(entity.getEntityCode());
1306
//    }
1307
//
1308
//    @Override
1309
//    public VCSGisWorkspaceChanges<VCSGisWorkspaceChange> getLocalChangesByEntityCode(String entityCode) {
1310
//        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1311
//        ChangesImpl changes = new ChangesImpl<WorkspaceChangeRow>(changesTable.getByEntityCode(this,entityCode),WorkspaceChangesTable.SELECTED) {
1312
//            @Override
1313
//            protected WorkspaceChangeRow createChange(Feature targetFeature) {
1314
//                return new WorkspaceChangeRow(VCSGisWorkspaceImpl.this, targetFeature);
1315
//            }
1316
//
1317
//            @Override
1318
//            protected void updateChange(FeatureStore store, WorkspaceChangeRow change) {
1319
//                change.update(store);
1320
//            }
1321
//
1322
//        };
1323
//        return changes;
1324
//    }
1325
    @Override
1326
    public VCSGisRepository getRepository() {
1327
        return repository;
1328
    }
1329

    
1330
    @Override
1331
    public List<VCSGisEntity> getEntitiesOfRemoteChanges() {
1332
        ArrayList<VCSGisEntity> res = new ArrayList<>();
1333
        RemoteChangesTable changesTable = new RemoteChangesTable();
1334
        DisposableFeatureSetIterable features = changesTable.getGroupedByEntity(this);
1335
        EntitiesRepoTable entitiesRepoTable = new EntitiesRepoTable();
1336
        for (Feature feature : features) {
1337
            VCSGisEntity entity = entitiesRepoTable.getByEntityCode((VCSGisRepositoryLocaldb) this.getRepository(), feature.getString(RemoteChangesTable.COD_ENTITY));
1338
            res.add(entity);
1339
        }
1340
        DisposeUtils.disposeQuietly(features);
1341
        return res;
1342
    }
1343

    
1344
    @Override
1345
    public VCSGisWorkspaceChanges<VCSGisRepositoryChange> getRemoteChanges() {
1346
        return getRemoteChangesByEntity(null);
1347
    }
1348

    
1349
    @Override
1350
    public VCSGisWorkspaceChanges<VCSGisRepositoryChange> getRemoteChangesByEntity(String entityName) {
1351
        String entityCode;
1352
        if (StringUtils.isBlank(entityName)) {
1353
            entityCode = null;
1354
        } else {
1355
            VCSGisEntity entity = this.getWorkspaceEntity(entityName);
1356
            if (entity == null) {
1357
                entity = this.getRepositoryEntity(entityName);
1358
                if (entity == null) {
1359
                    return null;
1360
                }
1361
            }
1362
            entityCode = entity.getEntityCode();
1363
        }
1364
        RemoteChangesTable changesTable = new RemoteChangesTable();
1365
        ChangesImpl changes = new ChangesImpl<RemoteChangeRow>(changesTable.getByEntityCode(this, entityCode), RemoteChangesTable.SELECTED) {
1366
            @Override
1367
            protected RemoteChangeRow createChange(Feature f) {
1368
                return new RemoteChangeRow(VCSGisWorkspaceImpl.this, f);
1369
            }
1370

    
1371
            @Override
1372
            protected void updateChange(FeatureStore store, RemoteChangeRow change) {
1373
                change.update(store);
1374
            }
1375

    
1376
        };
1377
        return changes;
1378
    }
1379

    
1380
    private Timestamp now() {
1381
        return Timestamp.from(LocalDateTime.now().toInstant(ZoneOffset.UTC));
1382
    }
1383

    
1384
    public List<VCSGisEntity> getEntitiesOfLocalChanges() {
1385
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1386
        List<VCSGisEntity> entities = new ArrayList<>();
1387

    
1388
        DisposableFeatureSetIterable changesGroupedByEntity = changesTable.getGroupedByEntity(this);
1389
        
1390
        for (Feature fchange : changesGroupedByEntity) {
1391
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1392
            VCSGisEntity localEntity = change.getEntity();
1393
            if (change.isSelected()) {
1394
                entities.add(localEntity);
1395
            }
1396
        }
1397
        return entities;  
1398
    }
1399
    
1400
    @SuppressWarnings("Convert2Lambda")
1401
    public boolean prepareCommitRequest(VCSGisCommitRequest request, Timestamp revisiondate, Timestamp efectivedate, String comment, SimpleTaskStatus status) {
1402
        boolean isMyStatus = false;
1403
        if (status == null) {
1404
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Prepare commit request");
1405
            status.setAutoremove(true);
1406
            status.add();
1407
            isMyStatus = true;
1408
        }
1409
        request.setEfectiveDate(efectivedate);
1410
        request.setRevisionDate(revisiondate);
1411
        request.setComment(comment);
1412
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1413

    
1414
        LOGGER.debug("===: COMMIT: Adding changed local entities");
1415
        status.message("Searching changed entities");
1416
        // adicionamos las entidades que vamos a actualizar con las revisiones que tenemos.
1417
        DisposableFeatureSetIterable changesGroupedByEntity = changesTable.getGroupedByEntity(this);
1418
//        status.setRangeOfValues(0, changesGroupedByEntity.size64());
1419
        status.setCurValue(0);
1420
        for (Feature fchange : changesGroupedByEntity) {
1421
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1422
            VCSGisEntity localEntity = change.getEntity();
1423
            LOGGER.debug("===: COMMIT: add used entity = " + fchange.toJson().toString().replace('\n', ' '));
1424
            if (change.isSelected()) {
1425
                request.add(request.createEntity(localEntity));
1426
            }
1427
            status.incrementCurrentValue();
1428
        }
1429
        changesGroupedByEntity.dispose();
1430

    
1431
        LOGGER.debug("===: COMMIT: Mark new local entities");
1432
        status.message("Searching new entities");
1433
        // Marcamos como nuevas las entidades que se han dado de alta.
1434
        DisposableFeatureSetIterable changesOfAddEntities = changesTable.getByOperation(this, OP_ADD_ENTITY);
1435
        for (Feature fchange : changesOfAddEntities) {
1436
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1437
            if (change.isSelected()) {
1438
                request.markAsNew(change.getEntity());
1439
            }
1440
        }
1441
        changesOfAddEntities.dispose();
1442

    
1443
        LOGGER.debug("===: COMMIT: Adding data");
1444
        status.message("Searching changed data");
1445
        // adicionamos los datos
1446
        boolean useSeleccion = true;
1447
        DisposableFeatureSetIterable changes = changesTable.getSelectedsWithoutAddEntity(this);
1448
        if (changes != null) {
1449
            request.add(new DisposableIterableAdapter(
1450
                    changes,
1451
                    new DisposableIterableAdapter.ItemConverter<Feature, VCSGisChange>() {
1452
                @Override
1453
                public VCSGisChange convert(Feature f) {
1454
                    return new WorkspaceChangeRow(VCSGisWorkspaceImpl.this, f);
1455
                }
1456
            }
1457
            )
1458
            );
1459
        }
1460
        if (isMyStatus) {
1461
            status.terminate();
1462
        }
1463
        return useSeleccion;
1464
    }
1465

    
1466
    @SuppressWarnings("Convert2Lambda")
1467
    public boolean prepareCommitRequest(String entity, VCSGisCommitRequest request, Timestamp revisiondate, Timestamp efectivedate, String comment, SimpleTaskStatus status) {
1468
        boolean isMyStatus = false;
1469
        if (status == null) {
1470
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Prepare commit request");
1471
            status.setAutoremove(true);
1472
            status.add();
1473
            isMyStatus = true;
1474
        }
1475
        request.setEfectiveDate(efectivedate);
1476
        request.setRevisionDate(revisiondate);
1477
        request.setComment(comment);
1478
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1479

    
1480
        LOGGER.debug("===: COMMIT: Adding changed local entities");
1481
        status.message("Searching changed entities");
1482
        //TODO:
1483
        // adicionamos las entidades que vamos a actualizar con las revisiones que tenemos.
1484
        DisposableFeatureSetIterable changesGroupedByEntity = changesTable.getGroupedByEntity(this);
1485
//        status.setRangeOfValues(0, changesGroupedByEntity.size64());
1486
        status.setCurValue(0);
1487
        for (Feature fchange : changesGroupedByEntity) {
1488
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1489
            VCSGisEntity localEntity = change.getEntity();
1490
            LOGGER.debug("===: COMMIT: add used entity = " + fchange.toJson().toString().replace('\n', ' '));
1491
            if (change.isSelected()) {
1492
                request.add(request.createEntity(localEntity));
1493
            }
1494
            status.incrementCurrentValue();
1495
        }
1496
        changesGroupedByEntity.dispose();
1497

    
1498
        LOGGER.debug("===: COMMIT: Mark new local entities");
1499
        status.message("Searching new entities");
1500
        //TODO
1501
        // Marcamos como nuevas las entidades que se han dado de alta.
1502
        DisposableFeatureSetIterable changesOfAddEntities = changesTable.getByOperation(this, OP_ADD_ENTITY);
1503
        for (Feature fchange : changesOfAddEntities) {
1504
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1505
            if (change.isSelected()) {
1506
                request.markAsNew(change.getEntity());
1507
            }
1508
        }
1509
        changesOfAddEntities.dispose();
1510

    
1511
        LOGGER.debug("===: COMMIT: Adding data");
1512
        status.message("Searching changed data");
1513
        // adicionamos los datos
1514
        boolean useSeleccion = true;
1515
        //TODO
1516
        DisposableFeatureSetIterable changes = changesTable.getSelectedsWithoutAddEntity(this, entity);
1517
        if (changes != null) {
1518
            request.add(new DisposableIterableAdapter(
1519
                    changes,
1520
                    new DisposableIterableAdapter.ItemConverter<Feature, VCSGisChange>() {
1521
                @Override
1522
                public VCSGisChange convert(Feature f) {
1523
                    return new WorkspaceChangeRow(VCSGisWorkspaceImpl.this, f);
1524
                }
1525
            }
1526
            )
1527
            );
1528
        }
1529
        if (isMyStatus) {
1530
            status.terminate();
1531
        }
1532
        return useSeleccion;
1533
    }
1534

    
1535
    @Override
1536
    public boolean canCommit() {
1537
        return canCommit(null);
1538
    }
1539

    
1540
    @Override
1541
    public boolean canCommit(MutableObject<String> message) {
1542

    
1543
        List<String> entityNames = new ArrayList<>();
1544
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1545
        DisposableFeatureSetIterable changesGroupedByEntity = null;
1546
        try {
1547

    
1548
            changesGroupedByEntity = changesTable.getGroupedByEntity(this);
1549
            for (Feature fchange : changesGroupedByEntity) {
1550
                WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1551
                VCSGisWorkspaceEntity entity = change.getEntity();
1552
                LOGGER.debug("===: CAN-COMMIT: add used entity = " + fchange.toJson().toString().replace('\n', ' '));
1553
                if (change.isSelected() && entity.isOutdated()) {
1554
                    entityNames.add(entity.getEntityName());
1555
                }
1556
            }
1557
            DisposeUtils.dispose(changesGroupedByEntity);
1558

    
1559
            if (!entityNames.isEmpty()) {
1560
                if (message != null) {
1561
                    I18nManager i18n = ToolsLocator.getI18nManager();
1562
                    String msg = i18n.getTranslation("_Tables_in_working_copy_are_outdated")
1563
                            + ". ("
1564
                            + StringUtils.join(entityNames, ", ")
1565
                            + ")";
1566
                    message.setValue(msg);
1567
                }
1568
                return false;
1569
            }
1570
            return true;
1571
        } catch (Exception ex) {
1572
            return false;
1573
        } finally {
1574
            DisposeUtils.dispose(changesGroupedByEntity);
1575
        }
1576
    }
1577

    
1578
    @Override
1579
    public List<VCSGisWorkspaceEntity> getEntitiesWithChanges() {
1580

    
1581
        List<VCSGisWorkspaceEntity> entities = new ArrayList<>();
1582
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1583
        DisposableFeatureSetIterable changesGroupedByEntity = null;
1584
        try {
1585

    
1586
            changesGroupedByEntity = changesTable.getGroupedByEntity(this);
1587
            for (Feature fchange : changesGroupedByEntity) {
1588
                WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1589
                VCSGisWorkspaceEntity entity = change.getEntity();
1590
                if (change.isSelected()) {
1591
                    entities.add(entity);
1592
                }
1593
            }
1594
            return entities;
1595

    
1596
        } catch (Exception ex) {
1597
            return null;
1598
        } finally {
1599
            DisposeUtils.dispose(changesGroupedByEntity);
1600
        }
1601
    }
1602

    
1603
    @Override
1604
    public int commit() {
1605
        return commit(null, now(), null, null);
1606
    }
1607

    
1608
    @Override
1609
    public int commit(Timestamp efectivedate, String comment, SimpleTaskStatus status) {
1610
        return commit(null, efectivedate, comment, status);
1611
    }
1612

    
1613
    @Override
1614
    @SuppressWarnings("Convert2Lambda")
1615
    public int commit(Timestamp revisiondate, Timestamp efectivedate, String comment, SimpleTaskStatus status) {
1616
        VCSGisCommitRequest request = null;
1617
        if (status == null) {
1618
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Commit");
1619
            status.setAutoremove(true);
1620
            status.add();
1621
        }
1622
        try {
1623
            LOGGER.debug("===: COMMIT " + this.getCode() + ", " + this.getLabel());
1624
            EntitiesTable entitiesTable = new EntitiesTable();
1625
            WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1626

    
1627
            status.message("Preparing commit");
1628
            reloadRepositoryEntities(status);
1629
            request = this.getRepository().createCommitRequest();
1630
            request.setAuthenticationToken(this.authenticationToken);
1631
            request.setUserCode(this.currentUser);
1632

    
1633
            boolean useSeleccion = this.prepareCommitRequest(request, revisiondate, efectivedate, comment, status);
1634

    
1635
            LOGGER.debug("===: COMMIT: Do execute request");
1636
            status.message("Executing commit request");
1637
            if ( execute(request) != ERR_OK) {
1638
                status.message("Can't commit changes (error " + request.getLastErrorCode() + ")");
1639
                status.abort();
1640
                return request.getLastErrorCode();
1641
            }
1642

    
1643
            LOGGER.debug("===: COMMIT: update local entities table");
1644
            status.message("Updating local metadata");
1645
            FeatureStore entitiesStore = null;
1646
            try {
1647
                entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1648
                entitiesStore.edit(FeatureStore.MODE_FULLEDIT);
1649
                List<VCSGisEntityEditable> changedLocalentities = request.getChangedLocalEntities();
1650
                status.setRangeOfValues(0, changedLocalentities.size());
1651
                status.setCurValue(0);
1652
                for (VCSGisEntity rentity : changedLocalentities) {
1653
                    EntityRow entityRow = entitiesTable.getByEntityName(this, rentity.getEntityName());
1654
                    if (entityRow != null) {
1655
                        entityRow.copyfrom(rentity);
1656
                        entityRow.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
1657
                        entityRow.update(entitiesStore);
1658
                    }
1659
                    status.incrementCurrentValue();
1660
                }
1661
                entitiesStore.finishEditing();
1662
                forceReloadWorkspaceEntities();
1663
            } catch (Exception e) {
1664
                FeatureStore.cancelEditingQuietly(entitiesStore);
1665
            } finally {
1666
                DisposeUtils.disposeQuietly(entitiesStore);
1667
                entitiesStore = null;
1668
            }
1669

    
1670
            LOGGER.debug("===: COMMIT: clean local changes");
1671
            status.message("Removing local list of changes");
1672
            if (useSeleccion) {
1673
                changesTable.deleteSelecteds(this);
1674
            } else {
1675
                changesTable.deleteAll(this);
1676
            }
1677
            status.message("Commit completed");
1678
            status.terminate();
1679
            return ERR_NO_ERROR;
1680
        } catch (Exception ex) {
1681
            LOGGER.warn("Can't commit changes.", ex);
1682
            status.message("Can't commit changes");
1683
            status.abort();
1684
            return ERR_CANT_COMMIT;
1685
        } finally {
1686
            DisposeUtils.disposeQuietly(request);
1687
        }
1688
    }
1689
    
1690
    public int commit(String entity, Timestamp revisiondate, Timestamp efectivedate, String comment, SimpleTaskStatus status) {
1691
        VCSGisCommitRequest request = null;
1692
        if (status == null) {
1693
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Commit");
1694
            status.setAutoremove(true);
1695
            status.add();
1696
        }
1697
        try {
1698
            LOGGER.debug("===: COMMIT " + this.getCode() + ", " + this.getLabel());
1699
            EntitiesTable entitiesTable = new EntitiesTable();
1700
            WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1701

    
1702
            status.message("Preparing commit");
1703
            reloadRepositoryEntities(status);
1704
            request = this.getRepository().createCommitRequest();
1705
            request.setAuthenticationToken(this.authenticationToken);
1706
            request.setUserCode(this.currentUser);
1707

    
1708
            boolean useSeleccion = this.prepareCommitRequest(entity, request, revisiondate, efectivedate, comment, status);
1709

    
1710
            LOGGER.debug("===: COMMIT: Do execute request");
1711
            status.message("Executing commit request");
1712
            if ( execute(request) != ERR_OK) {
1713
                status.message("Can't commit changes (error " + request.getLastErrorCode() + ")");
1714
                status.abort();
1715
                return request.getLastErrorCode();
1716
            }
1717

    
1718
            LOGGER.debug("===: COMMIT: update local entities table");
1719
            status.message("Updating local metadata");
1720
            FeatureStore entitiesStore = null;
1721
            try {
1722
                entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1723
                entitiesStore.edit(FeatureStore.MODE_FULLEDIT);
1724
                List<VCSGisEntityEditable> changedLocalentities = request.getChangedLocalEntities();
1725
                status.setRangeOfValues(0, changedLocalentities.size());
1726
                status.setCurValue(0);
1727
                for (VCSGisEntity rentity : changedLocalentities) {
1728
                    EntityRow entityRow = entitiesTable.getByEntityName(this, rentity.getEntityName());
1729
                    if (entityRow != null) {
1730
                        entityRow.copyfrom(rentity);
1731
                        entityRow.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
1732
                        entityRow.update(entitiesStore);
1733
                    }
1734
                    status.incrementCurrentValue();
1735
                }
1736
                entitiesStore.finishEditing();
1737
                forceReloadWorkspaceEntities();
1738
            } catch (Exception e) {
1739
                FeatureStore.cancelEditingQuietly(entitiesStore);
1740
            } finally {
1741
                DisposeUtils.disposeQuietly(entitiesStore);
1742
                entitiesStore = null;
1743
            }
1744

    
1745
            LOGGER.debug("===: COMMIT: clean local changes");
1746
            status.message("Removing local list of changes");
1747
            if (useSeleccion) {
1748
                changesTable.deleteSelecteds(this);
1749
            } else {
1750
                changesTable.deleteAll(this);
1751
            }
1752
            status.message("Commit completed");
1753
            status.terminate();
1754
            return ERR_NO_ERROR;
1755
        } catch (Exception ex) {
1756
            LOGGER.warn("Can't commit changes.", ex);
1757
            status.message("Can't commit changes");
1758
            status.abort();
1759
            return ERR_CANT_COMMIT;
1760
        } finally {
1761
            DisposeUtils.disposeQuietly(request);
1762
        }
1763
        
1764
    }
1765

    
1766

    
1767
    @Override
1768
    public int checkout(String tableName) {
1769
        return checkout(tableName, null);
1770
    }
1771

    
1772
    @Override
1773
    public int checkout(String tableName, String revisionCode) {
1774
        return checkout(tableName, revisionCode, null);
1775
    }
1776

    
1777
    @Override
1778
    public int checkout(String tableName, String revisionCode, SimpleTaskStatus status) {
1779
        FeatureStore target = null;
1780
        FeatureStore entitiesStore = null;
1781
        int errcode = ERR_OK;
1782
        VCSGisCheckoutRequest request = null;
1783
        if (status == null) {
1784
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("_Checkout");
1785
            status.setAutoremove(true);
1786
            status.add();
1787
        }
1788
        try {
1789
            LOGGER.debug("===: CHECKOUT " + this.getCode() + ", '" + this.getLabel() + "', " + tableName);
1790
            status.message("Preparing checkout");
1791
            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
1792
            if (lentity != null) {
1793
                status.message("Table " + tableName + " already exists");
1794
                status.abort();
1795
                return ERR_ENTITY_ALREADY_EXISTS;
1796
            }
1797
            reloadRepositoryEntities(status);
1798
            request = this.getRepository().createCheckoutRequest(tableName);
1799
            request.setAuthenticationToken(this.authenticationToken);
1800
            request.setUserCode(this.currentUser);
1801
            request.setEfectiveDate((Timestamp) null);
1802
            request.setRevisionCode(revisionCode);
1803

    
1804
            status.message("Executing checkout request for " + tableName);
1805
            if ( execute(request) != ERR_OK) {
1806
                status.message("Can't checkout " + tableName + " (error " + request.getLastErrorCode() + ")");
1807
                status.abort();
1808
                return request.getLastErrorCode();
1809
            }
1810
            status.message("Updating " + tableName + " metadata");
1811
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1812
            entitiesStore.edit(FeatureStore.MODE_FULLEDIT);
1813
            VCSGisEntity rentity = request.getEntity();
1814
            lentity = new EntityRow(this);
1815
            rentity.copyto(lentity);
1816
            lentity.insert(entitiesStore);
1817
            LOGGER.debug("===: CHECKOUT " + this.getCode() + ", '" + this.getLabel() + "', " + tableName + ", rev." + rentity.getRepositoryRevisionCode());
1818

    
1819
//            this.forceReloadWorkspaceEntities();
1820
            status.message("Creating table " + tableName);
1821
            this.create_table(lentity);
1822

    
1823
            status.message("Adding features in " + tableName);
1824
            errcode = ERR_CANT_OPEN_STORE;
1825
            target = this.openFeatureStore(lentity);
1826
            this.addStoreIgnoreChanges(target);
1827
            DisposableIterable<VCSGisRepositoryData> data = request.getData();
1828
//            long sz = ContainerUtils.size64(data); // Con tablas tochas esto deja frita la app.
1829
//            status.setRangeOfValues(0, sz);
1830
            status.setCurValue(0);
1831
            errcode = ERR_CANT_INSERT_FEATURES;
1832
            target.edit(FeatureStore.MODE_APPEND);
1833
            for (VCSGisRepositoryData d : data) {
1834
                EditableFeature f = target.createNewFeature(d.getDataAsJson());
1835
                target.insert(f);
1836
                status.incrementCurrentValue();
1837
            }
1838
            target.finishEditing();
1839

    
1840
            status.message("Updating " + tableName + " metadata");
1841
            if(StringUtils.isBlank(revisionCode)){
1842
                lentity.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
1843
            } else {
1844
                lentity.setLocalRevisionCode(revisionCode);
1845
            }
1846
            lentity.update(entitiesStore);
1847
            entitiesStore.finishEditing();
1848
            this.forceReloadWorkspaceEntities();
1849
            request.dispose();
1850

    
1851
            status.message("Checkout completed");
1852
            status.terminate();
1853
            return ERR_NO_ERROR;
1854
        } catch (Exception ex) {
1855
            LOGGER.warn("Can't checkout.", ex);
1856
            status.message("Can't checkout");
1857
            status.abort();
1858
            if (target != null) {
1859
                target.cancelEditingQuietly();
1860
            }
1861
            if (entitiesStore != null) {
1862
                entitiesStore.cancelEditingQuietly();
1863
            }
1864
            return errcode;
1865
        } finally {
1866
            DisposeUtils.disposeQuietly(request);
1867
            if (target != null) {
1868
                this.removeStoreIgnoreChanges(target);
1869
            }
1870
            DisposeUtils.disposeQuietly(target);
1871
            DisposeUtils.disposeQuietly(entitiesStore);
1872

    
1873
        }
1874
    }
1875

    
1876
    @Override
1877
    public int updateEntitiesFromRepository() {
1878
        return this.updateEntitiesFromRepository(null);
1879
    }
1880

    
1881
    @Override
1882
    public int updateEntitiesFromRepository(SimpleTaskStatus status) {
1883
        LOGGER.debug("===: UPDATE_ENTITIES " + this.getCode() + ", '" + this.getLabel() + "'");
1884
        FeatureStore entitiesStore = null;
1885
        EntitiesTable entitiesTable = new EntitiesTable();
1886
        if (status == null) {
1887
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Update metadata tables");
1888
            status.setAutoremove(true);
1889
            status.add();
1890
        }
1891
        try {
1892
            status.message("Preparing update metadata tables");
1893
            this.reloadRepositoryEntities(status);
1894

    
1895
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1896
            entitiesStore.edit(MODE_FULLEDIT);
1897
            for (VCSGisEntity rentity : this.getRepositoryEntities()) {
1898
                EntityRow entityRow = entitiesTable.getByEntityName(this, rentity.getEntityName());
1899
                if (entityRow != null) {
1900
                    rentity.copyto(entityRow);
1901
                    entityRow.update(entitiesStore);
1902
                }
1903
            }
1904
            entitiesStore.finishEditingQuietly();
1905

    
1906
            this.reloadWorkspaceEntities();
1907
            status.message("Update metadata tables completed");
1908
            status.terminate();
1909
            return ERR_OK;
1910
        } catch (Exception ex) {
1911
            LOGGER.warn("Can't update metadata tables.", ex);
1912
            status.message("Can't update metadata tables");
1913
            status.abort();
1914
            if (entitiesStore != null) {
1915
                entitiesStore.cancelEditingQuietly();
1916
            }
1917
            return ERR_CANT_UPDATE_ENTITIES;
1918
        } finally {
1919
            DisposeUtils.disposeQuietly(entitiesStore);
1920
            entitiesStore = null;
1921
        }
1922
    }
1923

    
1924
    @Override
1925
    public int updatePrepare(String tableName) {
1926
        return updatePrepare(tableName, null);
1927
    }
1928

    
1929
    @Override
1930
    public int updatePrepare(String tableName, SimpleTaskStatus status) {
1931
        LOGGER.debug("===: UPDATE_PREPARE: " + tableName + " WS " + this.getCode() + ", '" + this.getLabel() + "'");
1932
        if (status == null) {
1933
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Update-prepare " + tableName);
1934
            status.setAutoremove(true);
1935
            status.add();
1936
        }
1937

    
1938
        FeatureStore remoteChangesStore = null;
1939
        VCSGisUpdateRequest request = null;
1940
        DisposableIterable<VCSGisRepositoryData> remoteChanges = null;
1941
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1942
        FeatureStore userStore = null;
1943
        FeatureStore localChangesStore = null;
1944
        FeatureStore entitiesStore = null;
1945
        DataTransaction transaction = null;
1946
        try {
1947
            transaction = DALLocator.getDataManager().createTransaction();
1948
            transaction.begin();
1949
            transaction.add(this.getExplorer(), false);
1950

    
1951
            status.message("Preparing update-prepare");
1952
            reloadRepositoryEntities(status);
1953
            request = this.getRepository().createUpdateRequest(tableName);
1954
            transaction.add(request);
1955
            request.setAuthenticationToken(this.authenticationToken);
1956
            request.setUserCode(this.currentUser);
1957
            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
1958
            if (lentity != null) {
1959
                request.setLocalRevisionCode(lentity.getLocalRevisionCode());
1960
            }
1961
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1962
            transaction.add(entitiesStore);
1963
            status.message("Executing update-prepare request");
1964
            if ( execute(request) != ERR_OK) {
1965
                status.message("Can't update-prepare " + tableName + " (error " + request.getLastErrorCode() + ")");
1966
                status.abort();
1967
                return request.getLastErrorCode();
1968
            }
1969
            entitiesStore.edit(MODE_FULLEDIT);
1970
            status.message("Updating " + tableName + " metadata");
1971
            LOGGER.debug("===: UPDATE_PREPARE: " + tableName + " request code " + request.getCode());
1972
            VCSGisEntity rentity = request.getEntity();
1973
            if (lentity == null) {
1974
                lentity = new EntityRow(this);
1975
                lentity.copyfrom(rentity);
1976
                lentity.setLocalRevisionCode(null);
1977
                lentity.insert(entitiesStore);
1978
            } else {
1979
                lentity.copyfrom(rentity);
1980
                lentity.update(entitiesStore);
1981
            }
1982
//            this.reloadWorkspaceEntities();
1983
            String entityCode = lentity.getCode();
1984
            LOGGER.debug("===: UPDATE_PREPARE: " + tableName + " entity code " + entityCode + ", repo rev. " + lentity.getRepositoryRevisionCode() + ", local rev. " + lentity.getLocalRevisionCode());
1985

    
1986
            status.message("Preparing remote changes container");
1987
            remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
1988
            transaction.add(remoteChangesStore);
1989
            remoteChangesStore.edit(MODE_PASS_THROUGH);
1990

    
1991
            status.message("Deleting previous temporary remote changes");
1992
            LOGGER.debug("===: UPDATE_PREPARE: Delete updates table");
1993
            remoteChangesStore.delete("\"" + COD_ENTITY + "\"='" + entityCode + "'");
1994

    
1995
            remoteChanges = request.getData();
1996
            transaction.add(remoteChanges);
1997
//            long sz = ContainerUtils.size64(remoteChanges);
1998
//            status.setRangeOfValues(0, sz);
1999
            status.setCurValue(0);
2000

    
2001
            LOGGER.debug("===: UPDATE_PREPARE: Inserting updates");
2002
            userStore = this.openFeatureStore(lentity);
2003
            localChangesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
2004
            transaction.add(userStore);
2005
            transaction.add(localChangesStore);
2006
            localChangesStore.edit(MODE_PASS_THROUGH);
2007
            status.message("Downloading list of remote changes");
2008
            for (VCSGisRepositoryData remoteChange : remoteChanges) {
2009
                RemoteChangeRow remoteChangeRow = new RemoteChangeRow(this);
2010
//                LOGGER.debug("===: UPDATE_PREPARE: insert "+remoteChange.getFeatureRelatedCode()+", "+remoteChange.getOperation()+", "+remoteChange.getData());
2011
//                remoteChangeRow.setCode(remoteChange.getFeatureRelatedCode());
2012
                remoteChangeRow.newCode();
2013
                remoteChangeRow.setData(remoteChange.getData());
2014
                remoteChangeRow.setEntityCode(remoteChange.getEntityCode());
2015
                remoteChangeRow.setDataCode(remoteChange.getFeatureRelatedCode());
2016
                remoteChangeRow.setOperation(remoteChange.getOperation());
2017
                remoteChangeRow.setRevisionCode(remoteChange.getRevisionCode());
2018
                remoteChangeRow.setRevisionNumber(remoteChange.getRevisionNumber());
2019
                switch (remoteChange.getOperation()) {
2020
                    case OP_INSERT:
2021
                        remoteChangeRow.setStatus(STATE_LOCAL_NEW);
2022
                        break;
2023
                    case OP_UPDATE:
2024
                    case OP_DELETE:
2025
                        remoteChangeRow.setStatus(STATE_LOCAL_OUTDATED);
2026
                        break;
2027
                    default:
2028
                        remoteChangeRow.setStatus(STATE_LOCAL_UNMODIFIED);
2029
                        break;
2030
                }
2031

    
2032
                if (hasConflictRemoteChangeWithUserTable(lentity, remoteChange, userStore)) {
2033
                    remoteChangeRow.setStatus(STATE_CONFLICT);
2034
                    lentity.setState(STATE_CONFLICT);
2035
                }
2036

    
2037
                LOGGER.debug("===: UPDATE_PREPARE: row code = " + remoteChangeRow.getRelatedFeatureCode());
2038
                LOGGER.debug("===: UPDATE_PREPARE: row state = " + lentity.getState() + ", " + lentity.getStateLabel());
2039
                LOGGER.debug("===: UPDATE_PREPARE: row operation = " + remoteChangeRow.getOperation() + ", " + remoteChangeRow.getOperationLabel());
2040
                switch (lentity.getState()) {
2041
                    case STATE_LOCAL_OUTDATED:
2042
                    case STATE_LOCAL_UNMODIFIED:
2043
                        remoteChangeRow.setSelected(true);
2044
                        break;
2045
                    case STATE_CONFLICT:
2046
                        remoteChangeRow.setSelected(false);
2047
                        DisposableIterable<WorkspaceChangeRow> localChanges = changesTable.getChangesWidthUserData(this, lentity, remoteChangeRow, localChangesStore);
2048
                        if (localChanges != null) {
2049
                            for (WorkspaceChangeRow localChange : localChanges) {
2050
                                localChange.setStatus(STATE_CONFLICT);
2051
                                localChange.update(localChangesStore);
2052
                            }
2053
                            localChanges.dispose();
2054
                        }
2055
                    // Don't break to continue run next cases
2056
                    case STATE_LOCAL_NEW:
2057
                    case STATE_LOCAL_OUTDATED_AND_MODIFIED:
2058
                    case STATE_LOCAL_MODIFIED:
2059
                        WorkspaceChangeRow localChange = changesTable.getByEntityAndDataCode(this,
2060
                                entityCode,
2061
                                remoteChangeRow.getRelatedFeatureCode(),
2062
                                localChangesStore
2063
                        );
2064
                        if (localChange == null) {
2065
                            LOGGER.debug("===: UPDATE_PREPARE: no local modificacion, update local data");
2066
                            // Solo actualizamos si no ha sido modificado localmente y el cambio remoto no tiene conflictos
2067
                            if (remoteChangeRow.getStatus() != STATE_CONFLICT) {
2068
                                remoteChangeRow.setSelected(true);
2069
                            }
2070
                        } else {
2071
                            LOGGER.debug("===: UPDATE_PREPARE: not update. Local data is modified. " + localChange.getRelatedFeatureData().replace('\n', ' '));
2072
                            remoteChangeRow.setSelected(false);
2073
                            if (localChange.getStatus() != STATE_CONFLICT) {
2074
                                localChange.setStatus(STATE_LOCAL_OUTDATED_AND_MODIFIED);
2075
                                localChange.update(localChangesStore);
2076
                            }
2077
                        }
2078
                        break;
2079

    
2080
                }
2081
                remoteChangeRow.insert(remoteChangesStore);
2082
                status.incrementCurrentValue();
2083
            }
2084
            LOGGER.debug("===: UPDATE_PREPARE: finish inserting updates");
2085
            lentity.update(entitiesStore);
2086

    
2087
            remoteChangesStore.finishEditing();
2088
            localChangesStore.finishEditing();
2089
            entitiesStore.finishEditing();
2090

    
2091
            updateLocallyModyfiedRemoteChanges();
2092

    
2093
            transaction.commit();
2094

    
2095
            status.message("Update-prepare completed");
2096
            status.terminate();
2097
            return ERR_OK;
2098
        } catch (Exception ex) {
2099
            LOGGER.warn("Can't prepare update.", ex);
2100
            status.message("Can't prepare update");
2101
            status.abort();
2102
            DataTransaction.rollbackQuietly(transaction);
2103
            return ERR_CANT_PREPARE_UPDATE;
2104
        } finally {
2105
            DisposeUtils.disposeQuietly(transaction);
2106
        }
2107

    
2108
    }
2109

    
2110
    private void updateLocallyModyfiedRemoteChanges() {
2111

    
2112
        RemoteChangesTable changes = new RemoteChangesTable();
2113
        changes.updateStateFromLocalChanges(this, STATE_LOCAL_OUTDATED_AND_MODIFIED);
2114

    
2115
    }
2116

    
2117
    private boolean hasConflictRemoteChangeWithUserTable(VCSGisEntity lentity, VCSGisRepositoryData remoteChange, FeatureStore store) throws DataException {
2118
        if (store != null) {
2119
            FeatureType featType = lentity.getFeatureType();
2120
            JsonObject data = remoteChange.getDataAsJson();
2121
            ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
2122
            ExpressionBuilder builder = expManager.createExpressionBuilder();
2123
            builder.set(null);
2124
            for (FeatureAttributeDescriptor attr : featType) {
2125
                if (attr.isIndexed() && !attr.allowIndexDuplicateds()) {
2126
                    Object value = Json.toObject(data, attr.getName());
2127
                    builder.and(
2128
                            builder.eq(
2129
                                    builder.column(attr.getName()),
2130
                                    builder.constant(value)
2131
                            )
2132
                    );
2133

    
2134
                    Feature f = store.findFirst(builder.toString());
2135
                    if (f != null && !StringUtils.equals(
2136
                            f.getString(lentity.getFeatureIdFieldName()),
2137
                            remoteChange.getFeatureRelatedCode())) {
2138
                        return true;
2139
                    }
2140
                }
2141
            }
2142
        }
2143
        return false;
2144
    }
2145

    
2146
//    private Feature getUserFeatureConflictWithRemoteChange(VCSGisEntity lentity, RemoteChangeRow remoteChange, FeatureStore store) throws DataException {
2147
//        if(store != null) {
2148
//            FeatureType featType = lentity.getFeatureType();
2149
//            JsonObject data = remoteChange.getDataAsJson();
2150
//            ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
2151
//            ExpressionBuilder builder = expManager.createExpressionBuilder();
2152
//            builder.set(null);
2153
//            for (FeatureAttributeDescriptor attr : featType) {
2154
//                if(attr.isIndexed() && !attr.allowIndexDuplicateds()){
2155
//                    Object value = Json.toObject(data, attr.getName());
2156
//                    builder.and(
2157
//                        builder.eq(
2158
//                            builder.column(attr.getName()), 
2159
//                            builder.constant(value)
2160
//                        )
2161
//                    );
2162
//                    Feature targetFeature = store.findFirst(builder.toString());
2163
//                    if(targetFeature != null && !StringUtils.equals(
2164
//                            targetFeature.getString(lentity.getFeatureIdFieldName()),
2165
//                            remoteChange.getRelatedFeatureCode())
2166
//                        ){
2167
//                        return targetFeature;
2168
//                    }
2169
//                }
2170
//            }
2171
//        }
2172
//        return null;
2173
//    }
2174
    private DisposableFeatureSetIterable getUserFeaturesConflictWithRemoteChange(VCSGisEntity lentity, RemoteChangeRow remoteChange, FeatureStore store) throws DataException {
2175
        if (store == null) {
2176
            return null;
2177
        }
2178
        FeatureType featType = lentity.getFeatureType();
2179
        JsonObject data = remoteChange.getRelatedFeatureDataAsJson();
2180
        ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
2181
        ExpressionBuilder builder = expManager.createExpressionBuilder();
2182
        builder.set(null);
2183
        for (FeatureAttributeDescriptor attr : featType) {
2184
            if (StringUtils.equalsAnyIgnoreCase(lentity.getFeatureIdFieldName(), attr.getName())) {
2185
                continue;
2186
            }
2187
            if (attr.isIndexed() && !attr.allowIndexDuplicateds()) {
2188
                Object value = Json.toObject(data, attr.getName());
2189
                builder.or(
2190
                        builder.eq(
2191
                                builder.column(attr.getName()),
2192
                                builder.constant(value)
2193
                        )
2194
                );
2195
            }
2196
        }
2197
        ExpressionBuilder.Value value = builder.value();
2198
        if (value == null) {
2199
            return null;
2200
        }
2201
        ExpressionBuilder.BinaryOperator filter = builder.and(
2202
                builder.not(
2203
                        builder.eq(
2204
                                builder.column(lentity.getFeatureIdFieldName()),
2205
                                builder.constant(remoteChange.getRelatedFeatureCode())
2206
                        )
2207
                ),
2208
                value
2209
        );
2210

    
2211
        FeatureSet feats = store.getFeatureSet(filter.toString());
2212
        return feats.iterable();
2213
    }
2214

    
2215
    @Override
2216
    public int updateClean(String entityCode) {
2217
        return updateClean(entityCode, null);
2218
    }
2219

    
2220
    @Override
2221
    public int updateClean(String entityCode, SimpleTaskStatus status) {
2222
        VCSGisEntity entity = this.getEntity(entityCode);
2223
        if (entity == null) {
2224
            return ERR_ENTITY_NOT_EXISTS;
2225
        }
2226
        if (status == null) {
2227
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2228
                    "Update-clean " + entity.getEntityName()
2229
            );
2230
            status.setAutoremove(true);
2231
            status.add();
2232
        }
2233
        try {
2234
            status.message("Deleting temporary remote changes (" + entity.getEntityName() + ")");
2235
            RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2236
            remoteChangesTable.delete(this, entityCode);
2237
            status.message("Delete temporary remote changes completed");
2238
            status.terminate();
2239
            return ERR_OK;
2240
        } catch (Exception ex) {
2241
            LOGGER.warn("Can't deleting temporary remote changes of " + entity.getEntityName() + ".", ex);
2242
            status.message("Can't deleting temporary remote changes of " + entity.getEntityName() + ".");
2243
            status.abort();
2244
            return ERR_CANT_UPDATE_CLEAN;
2245
        }
2246

    
2247
    }
2248

    
2249
    @Override
2250
    public int update(String tableName) {
2251
        return this.update(tableName, false, false, null);
2252
    }
2253

    
2254
    @Override
2255
    public int update(String tableName, SimpleTaskStatus status) {
2256
        return this.update(tableName, false, false, status);
2257
    }
2258

    
2259
    @Override
2260
    public int merge(String tableName) {
2261
        return this.update(tableName, false, true, null);
2262
    }
2263

    
2264
    @Override
2265
    public int merge(String tableName, SimpleTaskStatus status) {
2266
        return this.update(tableName, false, true, status);
2267
    }
2268

    
2269
    public int update(String tableName, boolean prepare, boolean merge, SimpleTaskStatus status) {
2270
        int errcode = ERR_NO_ERROR;
2271
        if (status == null) {
2272
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2273
                    "Update " + tableName
2274
            );
2275
            status.setAutoremove(true);
2276
            status.add();
2277
        }
2278
        if (prepare) {
2279
            errcode = this.updatePrepare(tableName, status);
2280
            if (errcode != ERR_OK) {
2281
                return errcode;
2282
            }
2283
        }
2284
        LOGGER.debug("===: UPDATE " + this.getCode() + ", '" + this.getLabel() + "', " + tableName);
2285
        RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2286
        WorkspaceChangesTable localChangesTable = new WorkspaceChangesTable();
2287

    
2288
        EditableFeature ef;
2289
        DisposableFeatureSetIterable remoteChanges = null;
2290

    
2291
        FeatureStore workspaceChangesStore = null;
2292
        FeatureStore remoteChangesStore = null;
2293
        FeatureStore userStore = null;
2294
        FeatureStore entitiesStore = null;
2295

    
2296
        DataTransaction transaction = null;
2297
        try {
2298
            transaction = DALLocator.getDataManager().createTransaction();
2299
            transaction.begin();
2300

    
2301
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
2302
            transaction.add(entitiesStore);
2303
            entitiesStore.edit(MODE_PASS_THROUGH);
2304

    
2305
            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
2306
            if (lentity == null) {
2307
                lentity = new EntityRow(this);
2308
                VCSGisEntity rentity = this.getRepositoryEntityByName(tableName);
2309
                lentity.copyfrom(rentity);
2310
                lentity.setLocalRevisionCode(null);
2311
                lentity.update(entitiesStore);
2312
            }
2313
            if (!merge) {
2314
                status.message("Checking the need to merge");
2315
                if (remoteChangesTable.updateNeedMerge(this, lentity.getEntityCode())) {
2316
                    status.message("Can't update without merge.");
2317
                    status.abort();
2318
                    return ERR_UPDATE_NEED_MERGE;
2319
                }
2320
            }
2321
            String dataCodeFieldName = lentity.getFeatureIdFieldName();
2322
            status.message("Searching remote changes (" + lentity.getEntityName() + ")");
2323

    
2324
            userStore = this.openFeatureStore(lentity);
2325
            if (userStore == null) {
2326
                this.create_table(lentity);
2327
                userStore = this.openFeatureStore(lentity);
2328
            }
2329
            transaction.add(userStore);
2330
            userStore.edit(MODE_PASS_THROUGH);
2331

    
2332
            workspaceChangesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
2333
            transaction.add(workspaceChangesStore);
2334
            workspaceChangesStore.edit(MODE_PASS_THROUGH);
2335

    
2336
            remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
2337
            transaction.add(remoteChangesStore);
2338
            remoteChangesStore.edit(MODE_PASS_THROUGH);
2339

    
2340
            remoteChanges = remoteChangesTable.getSelectedsByEntityCodeAsIterator(this, lentity.getCode());
2341
            transaction.add(remoteChanges);
2342
//            long sz = ContainerUtils.size64(remoteChanges);
2343
//            status.setRangeOfValues(0, sz);
2344
            status.setCurValue(0);
2345

    
2346
            if (!remoteChanges.isEmpty()) {
2347
                this.addStoreIgnoreChanges(userStore);
2348
                status.message("Updating table (" + lentity.getEntityName() + ")");
2349
                FeatureType type = userStore.getDefaultFeatureTypeQuietly();
2350

    
2351
                ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
2352
                ExpressionBuilder builder = expManager.createExpressionBuilder();
2353

    
2354
                for (Feature feature : remoteChanges) {
2355
                    RemoteChangeRow remoteChangeRow = new RemoteChangeRow(this, feature);
2356
                    switch (remoteChangeRow.getOperation()) {
2357
                        case OP_INSERT:
2358
                            LOGGER.debug("===: UPDATE: insert");
2359
                            switch (remoteChangeRow.getStatus()) {
2360
                                case STATE_CONFLICT:
2361
                                    DisposableFeatureSetIterable feats = getUserFeaturesConflictWithRemoteChange(lentity, remoteChangeRow, userStore);
2362
                                    if (feats != null) {
2363
                                        for (Feature feat : feats) {
2364
                                            if (feat != null) {
2365
                                                userStore.delete(feat);
2366
                                                workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\" = '" + feat.getString(lentity.getFeatureIdFieldName()) + "'");
2367
                                            }
2368
                                        }
2369
                                        DisposeUtils.disposeQuietly(feats);
2370
                                    }
2371
                                //Don't break to do the default case
2372
                                default:
2373
                                    ef = userStore.createNewFeature(remoteChangeRow.getRelatedFeatureDataAsJson());
2374
                                    userStore.insert(ef);
2375
                                    break;
2376
                            }
2377
                            break;
2378
                        case OP_UPDATE:
2379
                            LOGGER.debug("===: UPDATE: update");
2380
                            JsonObject dataJson = remoteChangeRow.getRelatedFeatureDataAsJson();
2381
                            builder.set(null);
2382
                            for (FeatureAttributeDescriptor attr : type.getPrimaryKey()) {
2383
                                builder.and(
2384
                                        builder.eq(
2385
                                                builder.column(attr.getName()),
2386
                                                builder.constant(
2387
                                                        Json.toObject(dataJson.get(attr.getName()))
2388
                                                )
2389
                                        )
2390
                                );
2391
                            }
2392
                            Feature f = userStore.findFirst(builder.toString());
2393
                            if (f == null) {
2394
                                WorkspaceChangeRow localChange = localChangesTable.find(this, workspaceChangesStore, lentity.getEntityCode(), remoteChangeRow.getRelatedFeatureCode());
2395
                                if(localChange != null && localChange.getOperation() == OP_DELETE){
2396
                                    ef = userStore.createNewFeature(remoteChangeRow.getRelatedFeatureDataAsJson());
2397
                                    userStore.insert(ef);
2398
                                    break;
2399
                                } else {
2400
                                    throw new NullPointerException("Can't update null feature (" + builder.toString() + ").");
2401
                                }
2402
                            }
2403
                            ef = f.getEditable();
2404
                            ef.copyFrom(dataJson);
2405
                            userStore.update(ef);
2406
//                            workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\"='" + remoteChangeRow.getRelatedFeatureCode()+ "'");
2407
                            break;
2408

    
2409
                        case OP_DELETE:
2410
                            LOGGER.debug("===: UPDATE: delete");
2411
                            userStore.delete("\"" + dataCodeFieldName + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2412
//                            workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\"='" + remoteChangeRow.getRelatedFeatureCode()+ "'");
2413
                            break;
2414
                    }
2415
                    status.incrementCurrentValue();
2416
                }
2417
            }
2418

    
2419
            if (merge) {
2420
                status.message("Searching local changes to merge (" + lentity.getEntityName() + ")");
2421
                DisposeUtils.disposeQuietly(remoteChanges);
2422
                remoteChanges = remoteChangesTable.getNotSelectedsByEntityCodeAsIterator(this, lentity.getCode());
2423
                transaction.add(remoteChanges);
2424
//                sz = ContainerUtils.size64(remoteChanges);
2425
//                status.setRangeOfValues(0, sz);
2426
                status.setCurValue(0);
2427

    
2428
                if (!remoteChanges.isEmpty()) {
2429
                    //We edit the changesStore because we will need local changes 
2430
//                    workspaceChangesStore.edit(MODE_PASS_THROUGH);
2431

    
2432
                    //We edit the destination store because we may need to update some features (in case OP_DELETE)
2433
//                    userStore.edit(MODE_PASS_THROUGH);
2434
                    this.addStoreIgnoreChanges(userStore);
2435

    
2436
                    status.message("Adding to local changes (" + lentity.getEntityName() + ")");
2437
                    for (Feature feature : remoteChanges) {
2438
                        RemoteChangeRow remoteChangeRow = new RemoteChangeRow(this, feature);
2439
                        Feature f = userStore.findFirst("\"" + lentity.getFeatureIdFieldName() + "\" = '" + remoteChangeRow.getRelatedFeatureCode() + "'");
2440
                        switch (remoteChangeRow.getOperation()) {
2441
                            case OP_INSERT:
2442
                                LOGGER.debug("===: UPDATE: insert");
2443
                                if (f == null) {
2444
                                    this.addDeleteChange(lentity, workspaceChangesStore, remoteChangeRow.getRelatedFeatureCode(), null, null);
2445
                                } else {
2446
                                    this.addChange(lentity, OP_UPDATE, workspaceChangesStore, f, null);
2447
                                }
2448
                                break;
2449

    
2450
                            case OP_UPDATE:
2451
                                LOGGER.debug("===: UPDATE: update");
2452
                                if (f == null) {
2453
                                    this.addDeleteChange(lentity, workspaceChangesStore, remoteChangeRow.getRelatedFeatureCode(), null, null);
2454
                                } else {
2455
                                    this.addChange(lentity, OP_UPDATE, workspaceChangesStore, f, null);
2456
                                }
2457
                                break;
2458
                            case OP_DELETE:
2459
                                LOGGER.debug("===: UPDATE: delete");
2460
                                if (f != null) {
2461
                                    userStore.delete("\"" + dataCodeFieldName + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2462

    
2463
                                    ef = userStore.createNewFeature(f);
2464
                                    ef.setString(lentity.getFeatureIdFieldName(), this.createUniqueCode());
2465
                                    userStore.insert(ef);
2466

    
2467
                                    workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2468
                                    this.addChange(lentity, OP_INSERT, workspaceChangesStore, ef, null);
2469

    
2470
                                }
2471
                                break;
2472
                        }
2473
                        status.incrementCurrentValue();
2474
                    }
2475
                }
2476
            }
2477
            localChangesTable.removeLocalChangesRelatedToSelectedRemoteChanges(this, lentity);
2478
            remoteChangesTable.delete(remoteChangesStore, lentity.getEntityCode());
2479

    
2480
            status.message("Updating metadata tables");
2481
            lentity.setLocalRevisionCode(lentity.getRepositoryRevisionCode());
2482
            lentity.update(entitiesStore);
2483
            forceReloadWorkspaceEntities();
2484

    
2485
            transaction.commit();
2486

    
2487
            status.message("Update completed");
2488
            status.terminate();
2489
            return ERR_OK;
2490
        } catch (Exception ex) {
2491
            LOGGER.warn("Can't update.", ex);
2492
            status.message("Can't update");
2493
            status.abort();
2494
            return ERR_CANT_UPDATE;
2495
        } finally {
2496
            this.removeStoreIgnoreChanges(userStore);
2497
            DisposeUtils.disposeQuietly(transaction);
2498
        }
2499
    }
2500

    
2501
    @Override
2502
    public JDBCServerExplorer getExplorer() {
2503
        return this.wsexplorer;
2504
    }
2505

    
2506
//    @Override
2507
//    public int log(String tableName, int maxRevisions, int operation, SimpleTaskStatus status){
2508
//        
2509
//        
2510
//        FeatureStore localRevisionsStore = null;
2511
//        int errcode = ERR_OK;
2512
//        VCSGisLogRequest request = null;
2513
//        if( status==null ) {
2514
//            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2515
//                    "Log "+tableName
2516
//            );
2517
//            status.setAutoremove(true);
2518
//            status.add();
2519
//        }
2520
//        try {
2521
//            LOGGER.debug("===: LOG "+this.getCode()+", '"+this.getLabel()+"', "+tableName);
2522
//            reloadRepositoryEntities(status);
2523
//
2524
//            //TODO calcular las revisiones que tengo para excluirlas
2525
//            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
2526
//            if(lentity == null){
2527
//                status.message("Can't find table '"+tableName+"'");
2528
//                status.abort();
2529
//                return ERR_ENTITY_NOT_EXISTS;
2530
//            }
2531
//            
2532
//            
2533
//            LocalRevisionsTable localRevisionsTable = new LocalRevisionsTable();
2534
//            GetItemWithSizeAndIterator64<Feature> lrevisions = localRevisionsTable.getAllRevisions(this, lentity.getEntityCode());
2535
//            //Asumimos que lrevisions esta ordenado ascendentemente por numero de revision
2536
////            Long prevRevNumber = null;
2537
//            Long minRevision = null;
2538
//            Long maxRevision = null;
2539
//            for (Feature lrevision : lrevisions) {
2540
//                LocalRevisionRow x = new LocalRevisionRow(this, lrevision);
2541
//                Long revNumber = x.getNumber();
2542
//                //Asumimos que las revisiones que tenemos son consecutivas
2543
////                if(prevRevNumber != null && revNumber != prevRevNumber+1){ //Salto
2544
//                    //Borrar la tabla completamente ???
2545
////                    target = this.getFeatureStore(LocalRevisionsTable.TABLE_NAME);
2546
////                    target.edit(MODE_PASS_THROUGH);
2547
////                    target.delete
2548
////                }
2549
//                if(minRevision == null){
2550
//                    minRevision = revNumber;
2551
//                }
2552
//                maxRevision = revNumber;
2553
//            }
2554
//            
2555
//            status.message("Executing log request");
2556
//            request = this.getRepository().createLogRequest(tableName);
2557
//            if(minRevision != null && maxRevision != null){
2558
//                request.setExcludeRevisionsRange(Range.between(minRevision, maxRevision));
2559
//            }
2560
//            request.setOperation(operation);
2561
//            request.setMaxRevisions(maxRevisions);
2562
//            
2563
//            if( request.execute()!=ERR_OK ) {
2564
//                status.message("Can't retriev history of "+tableName+" (error "+request.getLastErrorCode()+")");
2565
//                status.abort();
2566
//                return request.getLastErrorCode();
2567
//            }
2568
//
2569
//            status.message("Deleting previous local revision information");
2570
//            errcode = ERR_CANT_OPEN_STORE;
2571
//            localRevisionsStore = this.openFeatureStore(LocalRevisionsTable.TABLE_NAME);
2572
//            errcode = ERR_CANT_RETRIEVE_SOURCE_FEATURES;
2573
//            DisposableIterable<VCSGisRevision> revisions = request.getRevisions();
2574
//            status.message("Adding to local revisions");
2575
//            long sz = ContainerUtils.size64(revisions);
2576
//            status.setRangeOfValues(0, sz);
2577
//            status.setCurValue(0);
2578
//            
2579
//            errcode = ERR_CANT_INSERT_FEATURES;
2580
//            localRevisionsStore.edit(FeatureStore.MODE_PASS_THROUGH);
2581
//            for (VCSGisRevision revision : revisions) {
2582
//                if(operation == VCSGisLogRequest.LOG_OP_LAST && revision.getNumber()!=maxRevision+1){
2583
//                    //Borrar todo el target ???
2584
//                }
2585
//                EditableFeature targetFeature = localRevisionsStore.createNewFeature();
2586
//                LocalRevisionRow row = new LocalRevisionRow(this, targetFeature);
2587
//                row.copyFrom(revision);
2588
//                row.insert(localRevisionsStore);
2589
//                status.incrementCurrentValue();
2590
//            }
2591
//            localRevisionsStore.finishEditing();
2592
//            status.message("Log completed");
2593
//            status.terminate();
2594
//            return ERR_OK;
2595
//        } catch (Exception ex) {
2596
//            LOGGER.warn("Can't retrieve history.", ex);
2597
//            FeatureStore.cancelEditingQuietly(localRevisionsStore);
2598
//            status.message("Can't retrieve history");
2599
//            status.abort();
2600
//            return errcode;
2601
//        } finally {
2602
//            DisposeUtils.disposeQuietly(request);
2603
//            if(localRevisionsStore != null) {
2604
//                this.removeStoreIgnoreChanges(localRevisionsStore);
2605
//            }
2606
//            DisposeUtils.disposeQuietly(localRevisionsStore);
2607
//        }
2608
//    }
2609
//
2610
//    @Override
2611
//    public List<VCSGisWorkspaceRevision> getRemoteRevisions(String tableName) {
2612
////        LocalRevisionsTable table = new LocalRevisionsTable();
2613
////        features = table.getAllRevisions(this, tableName);
2614
//        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
2615
//    }
2616
    @Override
2617
    public void reloadRepositoryEntities(SimpleTaskStatus status) {
2618
        boolean isMyStatus = false;
2619
        if (status == null) {
2620
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Repository tables");
2621
            status.setAutoremove(true);
2622
            status.add();
2623
            status.push();
2624
            isMyStatus = true;
2625
        }
2626
        FeatureStore store = null;
2627
        FeatureSet fset = null;
2628
        try {
2629
            status.message("Getting repository table metadata");
2630
            VCSGisEntitiesRequest request = this.getRepository().createEntitiesRequest();
2631
            request.setAuthenticationToken(this.authenticationToken);
2632
            request.setUserCode(this.currentUser);
2633
            if ( execute(request) != ERR_OK) {
2634
                throw new VCSGisRuntimeException(request.getLastErrorCode(), request.getLastErrorMessage());
2635
            }
2636
            List<VCSGisEntity> entities = request.getRepositoryEntities();
2637
            request.dispose();
2638

    
2639
            Map<String, VCSGisEntity> tmp = new HashMap<>();
2640
            entities.forEach(entity -> {
2641
                tmp.put(entity.getEntityCode(), entity);
2642
            });
2643
            this.repositoryEntitiesByCode = tmp;
2644
            
2645
            Map<String, EntityRow> theEntitiesByName = new HashMap<>();
2646
            Map<String, EntityRow> theEntitiesByCode = new HashMap<>();
2647

    
2648
            store = openFeatureStore(EntitiesTable.TABLE_NAME);
2649
            store.edit();
2650
            fset = store.getFeatureSet();
2651
            for (Feature feature : fset.iterable()) {
2652
                EntityRow entity = new EntityRow(this, feature);
2653
                VCSGisEntity repositoryEntity = this.repositoryEntitiesByCode.get(entity.getEntityCode());
2654
                if(repositoryEntity != null && !StringUtils.equalsIgnoreCase(entity.getRepositoryRevisionCode(),repositoryEntity.getRepositoryRevisionCode())){
2655
                    entity.setRepositoryRevisionCode(repositoryEntity.getRepositoryRevisionCode());
2656
                    entity.setTopologyPlanCode(repositoryEntity.getTopologyPlanCode());
2657
                    entity.update(store, fset);
2658
                }
2659
                theEntitiesByName.put(entity.getEntityName(), entity);
2660
                theEntitiesByCode.put(entity.getCode(), entity);
2661
            }
2662
            store.finishEditing();
2663
            this.workspaceEntitiesByName = theEntitiesByName;
2664
            this.workspaceEntitiesByCode = theEntitiesByCode;
2665

    
2666
            status.message("Repository tables metadata update completed");
2667
            if (isMyStatus) {
2668
                status.terminate();
2669
            }
2670
            this.repositoryEntitiesChangeListeners.fireEvent();
2671
            this.workspaceEntitiesChangeListeners.fireEvent();
2672
        } catch (VCSGisRuntimeException ex) {
2673
            FeatureStore.cancelEditingQuietly(store);
2674
            status.message("Can't get repository tables metadata");
2675
            if (isMyStatus) {
2676
                status.abort();
2677
            }
2678
            throw ex;
2679
        } catch (Exception ex) {
2680
            FeatureStore.cancelEditingQuietly(store);
2681
            status.message("Can't get repository tables metadata");
2682
            if (isMyStatus) {
2683
                status.abort();
2684
            }
2685
            throw new VCSGisRuntimeException(ERR_CANT_RETRIEVE_ENTITIES, VCSGisUtils.getErrorMessage(ERR_CANT_RETRIEVE_ENTITIES), ex);
2686
        } finally {
2687
            DisposeUtils.disposeQuietly(fset);
2688
            DisposeUtils.disposeQuietly(store);
2689
        }
2690
    }
2691

    
2692
    private boolean hasRepositoryEntities() {
2693
        return this.repositoryEntitiesByCode != null;
2694
    }
2695
    
2696
    @Override
2697
    public List<VCSGisEntity> getRepositoryEntities() {
2698
        if (this.repositoryEntitiesByCode == null) {
2699
            reloadRepositoryEntities(null);
2700
        }
2701
        List<VCSGisEntity> entities = new ArrayList<>(this.repositoryEntitiesByCode.values());
2702
        return entities;
2703
    }
2704

    
2705
    @Override
2706
    public boolean updateNeedMerge(String entityName) {
2707
        RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2708

    
2709
        VCSGisEntity entity = this.getWorkspaceEntity(entityName);
2710
        if (entity == null) {
2711
            entity = this.getRepositoryEntity(entityName);
2712
        }
2713

    
2714
        return remoteChangesTable.updateNeedMerge(this, entity.getEntityCode());
2715
    }
2716

    
2717
    @Override
2718
    public void addToConnectionPool() {
2719
        JDBCServerExplorerParameters params = this.getExplorerParameters();
2720
        DataManager dataManager = DALLocator.getDataManager();
2721
        dataManager.getDataServerExplorerPool().add(this.getLabel(), params);
2722
    }
2723

    
2724
    @Override
2725
    public boolean isInMyDatabase(FeatureStore store) {
2726
        if (!(store.getParameters() instanceof JDBCStoreParameters)) {
2727
            return false;
2728
        }
2729
        JDBCStoreParameters storeParams = (JDBCStoreParameters) store.getParameters();
2730
        JDBCServerExplorerParameters explorerParams = this.getExplorerParameters();
2731
        if (!StringUtils.equalsIgnoreCase(storeParams.getProviderName(), explorerParams.getProviderName())) {
2732
            return false;
2733
        }
2734
        return StringUtils.equalsIgnoreCase(storeParams.getUrl(), explorerParams.getUrl());
2735
    }
2736

    
2737
    @Override
2738
    public int history(String entityName, String group, Timestamp minDate, Timestamp maxDate, int maxNumberOfRevisions, SimpleTaskStatus status) {
2739
        int errcode = ERR_OK;
2740
        if (status == null) {
2741
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2742
                    "History" + entityName
2743
            );
2744
            status.setAutoremove(true);
2745
            status.add();
2746
        }
2747
        if (maxNumberOfRevisions < 0) {
2748
            maxNumberOfRevisions = 1000;
2749
        }
2750
        if (minDate != null && maxDate != null && minDate.compareTo(maxDate) > 0) {
2751
            Timestamp x = minDate;
2752
            minDate = maxDate;
2753
            maxDate = x;
2754
        }
2755
        DataTransaction transaction = DALLocator.getDataManager().createTransaction();
2756
        try {
2757
            LOGGER.debug("===: HISTORY " + this.getCode() + ", '" + this.getLabel() + "', " + entityName);
2758
            reloadWorkspaceEntities();
2759

    
2760
            VCSGisEntity lentity = this.getEntity(entityName);
2761
            if (lentity == null) {
2762
                status.message("Can't find table '" + entityName + "'");
2763
                status.abort();
2764
                return ERR_ENTITY_NOT_EXISTS;
2765
            }
2766

    
2767
            status.message("Executing history request");
2768
            VCSGisHistoryRequest request = this.getRepository().createHistoryRequest(entityName);
2769
            transaction.add(request);
2770

    
2771
            request.setAuthenticationToken(this.authenticationToken);
2772
            request.setUserCode(this.currentUser);
2773
            request.setDateRange(minDate, maxDate);
2774
            request.setMaxNumberOfRevisions(maxNumberOfRevisions);
2775
            request.setRevisionNumberRange(-1, -1);
2776

    
2777
            if ( execute(request) != ERR_OK) {
2778
                status.message("Can't retriev history of " + entityName + " (error " + request.getLastErrorCode() + ")");
2779
                status.abort();
2780
                return request.getLastErrorCode();
2781
            }
2782
            LocalRevisionsTable localRevisionsTable = new LocalRevisionsTable();
2783
            FeatureStore localRevisionsStore = this.openFeatureStore(LocalRevisionsTable.TABLE_NAME);
2784
            transaction.add(localRevisionsStore);
2785
            localRevisionsStore.edit(MODE_PASS_THROUGH);
2786

    
2787
            status.message("Deleting previous local revision information");
2788
            localRevisionsTable.deleteByEntityCodeAndGroup(
2789
                    this,
2790
                    localRevisionsStore,
2791
                    lentity.getEntityCode(),
2792
                    group
2793
            );
2794

    
2795
            DisposableIterable<VCSGisRevision> revisions = request.getRevisions();
2796
            status.message("Adding to local revisions");
2797
//            long sz = ContainerUtils.size64(revisions);
2798
//            status.setRangeOfValues(0, sz);
2799
            status.setCurValue(0);
2800

    
2801
            long minRevision = -1;
2802
            minDate = now();
2803
            errcode = ERR_CANT_INSERT_FEATURES;
2804
            for (VCSGisRevision revision : revisions) {
2805
                LocalRevisionRow row = new LocalRevisionRow(this);
2806
                row.copyFrom(revision);
2807
                row.setGroup(group);
2808
                row.insert(localRevisionsStore);
2809
                if (minRevision < 0 || minRevision > row.getNumber()) {
2810
                    minRevision = row.getNumber();
2811
                }
2812
                if (minDate.compareTo(row.getRevisionDate()) > 0) {
2813
                    minDate = row.getRevisionDate();
2814
                }
2815
                status.incrementCurrentValue();
2816
            }
2817
            localRevisionsStore.finishEditing();
2818

    
2819
            VarsTable varsTable = new VarsTable();
2820
            varsTable.set(
2821
                    this,
2822
                    "history_" + entityName + "_" + group + "_MinDate",
2823
                    minDate.toString()
2824
            );
2825
            varsTable.set(
2826
                    this,
2827
                    "history_" + entityName + "_" + group + "_MinRevision",
2828
                    String.valueOf(minRevision)
2829
            );
2830

    
2831
            transaction.commit();
2832
            status.message("History completed");
2833
            status.terminate();
2834
            return ERR_OK;
2835
        } catch (Exception ex) {
2836
            LOGGER.warn("Can't retrieve history.", ex);
2837
            transaction.rollbackQuietly();
2838
            status.message("Can't retrieve history");
2839
            status.abort();
2840
            return errcode;
2841
        } finally {
2842
            transaction.dispose();
2843
        }
2844
    }
2845

    
2846
    @Override
2847
    public int history(String entityName, String group, int maxNumberOfRevisions, SimpleTaskStatus status) {
2848
        int errcode = ERR_OK;
2849
        if (status == null) {
2850
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2851
                    "History" + entityName
2852
            );
2853
            status.setAutoremove(true);
2854
            status.add();
2855
        }
2856
        if (maxNumberOfRevisions < 0) {
2857
            maxNumberOfRevisions = 1000;
2858
        }
2859
        DataTransaction transaction = DALLocator.getDataManager().createTransaction();
2860
        try {
2861
            LOGGER.debug("===: HISTORY " + this.getCode() + ", '" + this.getLabel() + "', " + entityName);
2862
            reloadWorkspaceEntities();
2863

    
2864
            EntityRow lentity = this.getWorkspaceEntityByName(entityName);
2865
            if (lentity == null) {
2866
                status.message("Can't find table '" + entityName + "'");
2867
                status.abort();
2868
                return ERR_ENTITY_NOT_EXISTS;
2869
            }
2870
            VarsTable varsTable = new VarsTable();
2871

    
2872
            long minRevision = Long.valueOf(varsTable.get(this, "history_" + entityName + "_" + group + "_MinRevision"));
2873

    
2874
            status.message("Executing history request");
2875
            VCSGisHistoryRequest request = this.getRepository().createHistoryRequest(entityName);
2876
            transaction.add(request);
2877

    
2878
            request.setAuthenticationToken(this.authenticationToken);
2879
            request.setUserCode(this.currentUser);
2880
            request.setDateRange(null, null);
2881
            request.setMaxNumberOfRevisions(maxNumberOfRevisions);
2882
            request.setRevisionNumberRange(-1, minRevision);
2883

    
2884
            if ( execute(request) != ERR_OK) {
2885
                status.message("Can't retriev history of " + entityName + " (error " + request.getLastErrorCode() + ")");
2886
                status.abort();
2887
                return request.getLastErrorCode();
2888
            }
2889
            FeatureStore localRevisionsStore = this.openFeatureStore(LocalRevisionsTable.TABLE_NAME);
2890
            transaction.add(localRevisionsStore);
2891
            localRevisionsStore.edit(MODE_PASS_THROUGH);
2892

    
2893
            DisposableIterable<VCSGisRevision> revisions = request.getRevisions();
2894
            status.message("Adding to local revisions");
2895
//            long sz = ContainerUtils.size64(revisions);
2896
//            status.setRangeOfValues(0, sz);
2897
            status.setCurValue(0);
2898

    
2899
            errcode = ERR_CANT_INSERT_FEATURES;
2900
            minRevision = -1;
2901
            Timestamp minDate = now();
2902
            for (VCSGisRevision revision : revisions) {
2903
                LocalRevisionRow row = new LocalRevisionRow(this);
2904
                row.copyFrom(revision);
2905
                row.setGroup(group);
2906
                if (!row.exists(localRevisionsStore)) {
2907
                    row.insert(localRevisionsStore);
2908
                }
2909
                if (minRevision < 0 || minRevision > row.getNumber()) {
2910
                    minRevision = row.getNumber();
2911
                }
2912
                if (minDate.compareTo(row.getRevisionDate()) > 0) {
2913
                    minDate = row.getRevisionDate();
2914
                }
2915
                status.incrementCurrentValue();
2916
            }
2917
            localRevisionsStore.finishEditing();
2918

    
2919
            varsTable.set(
2920
                    this,
2921
                    "history_" + entityName + "_" + group + "_MinDate",
2922
                    minDate.toString()
2923
            );
2924
            varsTable.set(
2925
                    this,
2926
                    "history_" + entityName + "_" + group + "_MinRevision",
2927
                    String.valueOf(minRevision)
2928
            );
2929

    
2930
            transaction.commit();
2931
            status.message("history completed");
2932
            status.terminate();
2933
            return ERR_OK;
2934
        } catch (Exception ex) {
2935
            LOGGER.warn("Can't retrieve history.", ex);
2936
            transaction.rollbackQuietly();
2937
            status.message("Can't retrieve history");
2938
            status.abort();
2939
            return errcode;
2940
        } finally {
2941
            transaction.dispose();
2942
        }
2943
    }
2944

    
2945
    @Override
2946
    public GetItemWithSize64<VCSGisRevision> getRevisions(String entityName, String group) {
2947
        LocalRevisionsTable localRevisionsTable = new LocalRevisionsTable();
2948
        reloadWorkspaceEntities();
2949

    
2950
        VCSGisEntity lentity = this.getEntity(entityName);
2951
        if (lentity == null) {
2952
            throw new IllegalArgumentException("EntityName '" + entityName + "' not found.");
2953
        }
2954
        final VCSGisWorkspaceImpl workspace = this;
2955
        final GetItemWithSizeAndIterator64<Feature> revisionsf = localRevisionsTable.getRevisions(this, lentity.getEntityCode(), group);
2956
        GetItemWithSize64<VCSGisRevision> revisions = new GetItemWithSize64<VCSGisRevision>() {
2957
            @Override
2958
            public long size64() {
2959
                return revisionsf.size64();
2960
            }
2961

    
2962
            @Override
2963
            public VCSGisRevision get64(long position) {
2964
                Feature f = revisionsf.get64(position);
2965
                LocalRevisionRow revision = new LocalRevisionRow(workspace, f);
2966
                return revision;
2967
            }
2968
        };
2969
        return revisions;
2970
    }
2971

    
2972
    @Override
2973
    public String getUserName(String userCode) {
2974
        return null;
2975
    }
2976

    
2977
    @Override
2978
    public VCSGisUser getUser(String userCode) {
2979
        return null;
2980
    }
2981

    
2982
    @Override
2983
    public Feature getRelatedFeature(VCSGisEntity entity, String featureCode) {
2984
        try {
2985
            FeatureStore store = this.getFeatureStore(entity.getEntityName());
2986
            Feature f = store.findFirst("\"" + entity.getFeatureIdFieldName() + "\"='" + featureCode + "'");
2987
            return f;
2988
        } catch (Exception ex) {
2989
            throw new RuntimeException("Can't retrieve feature '" + entity.getEntityName() + "/" + code + "'.", ex);
2990
        }
2991

    
2992
    }
2993

    
2994
    @Override
2995
    public Feature getRelatedFeature(VCSGisRepositoryChange change) {
2996
        EntityRow entity = this.getWorkspaceEntity(change.getEntityCode());
2997
        return getRelatedFeature(entity, change.getRelatedFeatureCode());
2998
    }
2999
    
3000
    @Override
3001
    public int removeEntity(String nameOrCode) {
3002
        int err = ERR_NO_ERROR;
3003
        EntityRow entity = this.getWorkspaceEntity(nameOrCode);
3004
        if(entity == null){
3005
            err = ERR_ENTITY_NOT_EXISTS;
3006
            return err;
3007
        }
3008

    
3009
        DataTransaction transaction = DALLocator.getDataManager().createTransaction();
3010
        try {
3011
            LOGGER.debug("===: REMOVE ENTITY " + entity.getEntityName());
3012

    
3013

    
3014
            //Eliminamos todos los cambios de esta entidad
3015
            err = ERR_CANT_REMOVE_CHANGES;
3016
            FeatureStore changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
3017
            transaction.add(changesStore);
3018
            changesStore.edit(MODE_FULLEDIT);
3019
            changesStore.delete("\""+WorkspaceChangesTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3020
            changesStore.finishEditing();
3021

    
3022
            FeatureStore remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
3023
            transaction.add(remoteChangesStore);
3024
            remoteChangesStore.edit(MODE_FULLEDIT);
3025
            remoteChangesStore.delete("\""+RemoteChangesTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3026
            remoteChangesStore.finishEditing();
3027

    
3028
            //Eliminamos las revisiones locales
3029
            FeatureStore revisionsStore = openFeatureStore(LocalRevisionsTable.TABLE_NAME);       
3030
            transaction.add(revisionsStore);
3031
            revisionsStore.edit(MODE_FULLEDIT);
3032
            revisionsStore.delete("\""+LocalRevisionsTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3033
            revisionsStore.finishEditing();
3034
            err = ERR_CANT_REMOVE_ENTITY;
3035

    
3036

    
3037
            //Eliminamos la entidad
3038
            FeatureStore entitiesStore = openFeatureStore(EntitiesTable.TABLE_NAME);       
3039
            transaction.add(entitiesStore);
3040
            entitiesStore.edit(MODE_FULLEDIT);
3041
            entitiesStore.delete("\""+EntitiesTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3042
            entitiesStore.finishEditing();
3043
            err = ERR_CANT_REMOVE_ENTITY;
3044

    
3045

    
3046
            //Eliminamos el DALFILE
3047
            FeatureStore store = this.openFeatureStore(entity);
3048
            if(store != null){
3049
                transaction.add(store);
3050
                ResourcesStorage resourcesStorage = store.getResourcesStorage();
3051
                if (resourcesStorage != null) {
3052
                    Resource resource = resourcesStorage.getResource("dal");
3053
                    if (resource != null) {
3054
                        resourcesStorage.remove(resource.getName());
3055
                    }
3056
                }
3057
            
3058
                //Eliminamos el store
3059
                transaction.add(this.wsexplorer, false);
3060
                this.wsexplorer.remove(store.getParameters());
3061
            }
3062
            
3063
            forceReloadWorkspaceEntities();
3064
            transaction.commit();
3065
            return ERR_OK;
3066
        } catch (Exception ex) {
3067
            LOGGER.warn("Can't remove entity.", ex);
3068
            transaction.rollbackQuietly();
3069
            return err;
3070
        } finally {
3071
            transaction.dispose();
3072
        }
3073
        
3074
    }
3075

    
3076
    public int authenticate(String userId, String password, SimpleTaskStatus status) {
3077
        int errcode = ERR_OK;
3078
        if (status == null) {
3079
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
3080
                    "Authenticate-" + userId
3081
            );
3082
            status.setAutoremove(true);
3083
            status.add();
3084
        }
3085
        try {
3086
            VCSGisAuthenticateRequest request = this.getRepository().createAuthenticateRequest(userId, password);
3087
            if ( execute(request) != ERR_OK) {
3088
                status.message(request.getLastErrorMessage());
3089
                status.abort();
3090
                return request.getLastErrorCode();
3091
            }
3092
            VarsTable varsTable = new VarsTable();
3093
            varsTable.set(this,"USER",request.getUserCode());
3094
            varsTable.set(this,"AUTHENTICATIONTOKEN",request.getAuthenticationToken());
3095
            this.currentUser = request.getUserCode();
3096
            this.authenticationToken = request.getAuthenticationToken();
3097
            status.message("Authentication completed");
3098
            status.terminate();
3099
            return ERR_OK;
3100
        } catch (Exception ex) {
3101
            LOGGER.warn("Can't authenticate user.", ex);
3102
            status.message("Can't authenticate user");
3103
            status.abort();
3104
            return errcode;
3105
        }
3106
    }
3107

    
3108
    @Override
3109
    public void setUserIdentificationRequester(VCSGisUserIdentificationRequester userIdentificationRequester) {
3110
        this.userIdentificationRequester = userIdentificationRequester;
3111
    }
3112

    
3113
    private int execute(VCSGisRequest request) {
3114
        while(true) {
3115
            switch(request.execute()) {
3116
                case ERR_CANT_AUTHENTICATE_USER:
3117
                case ERR_INVALID_AUTHENTICATION_TOKEN:
3118
                case ERR_USER_NOT_AUTHORIZED:
3119
                case ERR_AUTHENTICATION_EXPIRED:
3120
                case ERR_INVALID_USERCODE:
3121
                    if( this.userIdentificationRequester!= null ) {
3122
                        if( this.userIdentificationRequester.requestIdentification() ) {
3123
                            continue;
3124
                        }
3125
                    }
3126
                default:
3127
                    return request.getLastErrorCode();            
3128
            }
3129
        }
3130
    }
3131

    
3132

    
3133
    // TODO: eliminar la constante y contains para usar las de tools.
3134
    public static final Comparator<String> EQUALS_IGNORECASE_COMPARATOR = (Comparator<String>) (String o1, String o2) -> StringUtils.compareIgnoreCase(o1, o2);
3135
    public static boolean contains(Collection collection, Object value, Comparator comparator) {
3136
        for (Object item : collection) {
3137
            if( comparator.compare(item, value)==0 ) {
3138
                return true;
3139
            }
3140
        }
3141
        return false;
3142
    }
3143

    
3144
    @Override
3145
    public Collection<String> getEntityCategories() {
3146
        List<String> categories = new ArrayList<>();
3147
        if( this.hasRepositoryEntities() ) {
3148
            for (VCSGisEntity entity : this.getRepositoryEntities()) {
3149
                String category = entity.getCategory();
3150
                if( StringUtils.isNotBlank(category) ) {
3151
                    if( !contains(categories, category, EQUALS_IGNORECASE_COMPARATOR) ) {
3152
                        categories.add(category);
3153
                    }
3154
                }
3155
            }
3156
        }
3157
        for (VCSGisEntity entity : this.getWorkspaceEntities()) {
3158
            String category = entity.getCategory();
3159
            if( StringUtils.isNotBlank(category) ) {
3160
                if( !contains(categories, category, EQUALS_IGNORECASE_COMPARATOR) ) {
3161
                    categories.add(category);
3162
                }
3163
            }
3164
        }
3165
        Collections.sort(categories);
3166
        return Collections.unmodifiableCollection(categories);
3167
    }
3168
    
3169
    @Override
3170
    public String getTopologyPlan(String topologyPlanCode) {
3171
        if( StringUtils.isBlank(topologyPlanCode) ) {
3172
            return null;
3173
        }
3174
        TopologyplanTable topologyplanTable = new TopologyplanTable();
3175
        return topologyplanTable.getByCode(this, topologyPlanCode);
3176
    }
3177
    
3178
    @Override
3179
    public int importHistory(FeatureStore sourceStore,
3180
            String name,
3181
            String label,
3182
            String category,
3183
            String attrNameForLabel,
3184
            String fieldCodeName,
3185
            String fieldDateName,
3186
            String fieldOrderName) {
3187
        
3188
            I18nManager i18n = ToolsLocator.getI18nManager();
3189
            SimpleTaskStatus status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(i18n.getTranslation("_Import_history"));
3190
            status.setAutoremove(true);
3191
            status.add();
3192
            
3193
            FeatureStore target = null;
3194
            FeatureSet features = null;
3195
            
3196
        try{
3197
            VCSGisRepository repo = this.getRepository();
3198
            if (repo instanceof VCSGisRepositoryLocaldb){
3199
                ((VCSGisRepositoryLocaldb) repo).setAllowAssignTheRevisionDate(true);
3200
            }
3201
            
3202
            int result = this.addEntity(
3203
                    sourceStore.getDefaultFeatureTypeQuietly(),
3204
                    name, 
3205
                    null,
3206
                    attrNameForLabel, 
3207
                    category, 
3208
                    label,
3209
                    null
3210
            );
3211
            target = this.openFeatureStore(name);
3212
            FeatureQuery query = sourceStore.createFeatureQuery();
3213
            ExpressionBuilder expBuilder = ExpressionUtils.createExpressionBuilder();
3214
            query.getOrder().add(fieldDateName, true);
3215
            query.getOrder().add(fieldOrderName, true);
3216
            features = sourceStore.getFeatureSet(query);
3217
            target.edit(MODE_PASS_THROUGH);
3218
            Timestamp lastRevisionDate=null;
3219
            status.setRangeOfValues(0, features.size64());
3220
            status.setCurValue(0);
3221
            for (Feature sourceFeature : features) {
3222
                String filter = expBuilder.eq(expBuilder.column(fieldCodeName),
3223
                        expBuilder.constant(sourceFeature.get(fieldCodeName))
3224
                ).toString();
3225
                Feature targetFeature = target.findFirst(filter);
3226
                if (targetFeature == null) {
3227
                    if (lastRevisionDate==null){
3228
                        lastRevisionDate=sourceFeature.getTimestamp(fieldDateName);
3229
                    }
3230
                    if (Objects.equals(lastRevisionDate, sourceFeature.getTimestamp(fieldDateName))){
3231
                        EditableFeature editableTargetFeature = target.createNewFeature(sourceFeature);
3232
                        target.insert(editableTargetFeature);
3233
                    }else{
3234
                        result = this.commit(lastRevisionDate, lastRevisionDate, null, null);
3235
                        if (result!=ERR_OK){
3236
                            return result;
3237
                        }
3238
                        EditableFeature editableTargetFeature = target.createNewFeature(sourceFeature);
3239

    
3240
                        target.insert(editableTargetFeature);
3241
                        lastRevisionDate=sourceFeature.getTimestamp(fieldDateName);                       
3242
                    }
3243
                
3244
                }else{
3245
                    EditableFeature ef = targetFeature.getEditable();
3246
                    ef.copyFrom(sourceFeature);
3247
                    ef.setUpdatable(true);
3248
                    target.update(ef);
3249
                }
3250
                status.incrementCurrentValue();
3251
            }
3252
            result = this.commit(lastRevisionDate, lastRevisionDate, null, null);
3253
            if (result!=ERR_OK){
3254
                return result;
3255
            }
3256
            target.finishEditing();
3257
            status.terminate();
3258
            return ERR_OK;
3259
        }catch(Exception ex){
3260
            status.abort();
3261
            return -1;
3262
        }finally{
3263
            DisposeUtils.disposeQuietly(features);
3264
            DisposeUtils.disposeQuietly(target);
3265
        }
3266
    }
3267
    public int revert(String nameOrCode) {
3268
        return revert(nameOrCode, null);
3269
    }
3270
    
3271
    @Override
3272
    public int revert(String nameOrCode, SimpleTaskStatus status) {
3273
        if (status == null) {
3274
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Commit");
3275
            status.setAutoremove(true);
3276
            status.add();
3277
        }
3278

    
3279
//        FeatureStore entitiesStore = null;
3280

    
3281
        DataTransaction transaction = null;
3282
        try {
3283
            LOGGER.debug("===: REVERT " + this.getCode() + ", " + this.getLabel() + ", " + nameOrCode);
3284
            transaction = DALLocator.getDataManager().createTransaction();
3285
            transaction.begin();
3286
            
3287
            status.message("Reverting");
3288
            
3289
            EntityRow entity = this.getWorkspaceEntity(nameOrCode);
3290
            WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
3291
            FeatureStore userStore = null;
3292
            FeatureStore changesStore = null;
3293
//            String dataCodeFieldName = entity.getFeatureIdFieldName();
3294

    
3295
            DisposableFeatureSetIterable changes = changesTable.getSelectedsByEntityCodeAsIterator(this, entity.getEntityCode());
3296
            transaction.add(changes);
3297

    
3298

    
3299
            if (!changes.isEmpty()) {
3300
                userStore = this.openFeatureStore(entity);
3301
                transaction.add(userStore, true);
3302
                userStore.edit(MODE_PASS_THROUGH);
3303
                changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
3304
                transaction.add(changesStore, true);
3305
                changesStore.edit(MODE_PASS_THROUGH);
3306

    
3307
                status.setCurValue(0);
3308
                status.setRangeOfValues(0, changes.size64());
3309
                for (Feature feature : changes) {
3310
                    WorkspaceChangeRow change = new WorkspaceChangeRow(this, feature);
3311
                    change.revert(userStore, changesStore);
3312
//                    String data = change.getData();
3313
//                    JsonObject dataAsJson = change.getDataAsJson();
3314
//                    int operation = change.getOperation();
3315
//                    switch (change.getOperation()) {
3316
//                        case OP_ADD_ENTITY:
3317
//                            //TODO: remove entity ???
3318
////                            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
3319
////                            transaction.add(entitiesStore);
3320
////                            entitiesStore.edit(MODE_PASS_THROUGH);
3321
//                            break;
3322
//                        case OP_INSERT:
3323
//                            // Remove related feature
3324
//                            LOGGER.debug("===: REVERT: insert");
3325
//                            userStore.delete("\"" + dataCodeFieldName + "\"='" + change.getRelatedFeatureCode() + "'");
3326
//                            break;
3327
//                        case OP_UPDATE:
3328
//                            // Update related feature from old feature
3329
//                            Feature relatedFeature = change.getRelatedFeature();
3330
//                            EditableFeature ef = relatedFeature.getEditable();
3331
//                            ef.copyFrom(change.getDataAsJson());
3332
//                            userStore.update(ef);
3333
//                            break;
3334
//                        case OP_DELETE:
3335
//                            //Create new feature from old feature
3336
//                            JsonObject dataJson = change.getDataAsJson();
3337
//                            ef = userStore.createNewFeature(dataJson);
3338
//                            userStore.insert(ef);
3339
//                            break;
3340
//                    }
3341
                    status.incrementCurrentValue();
3342
                }
3343
                userStore.finishEditing();
3344
                changesStore.finishEditing();
3345
            }
3346
            
3347

    
3348
//            LOGGER.debug("===: REVERT: clean local changes");
3349
//            status.message("Removing local list of changes");
3350
//            changesTable.deleteSelectedsByEntity(this, entity.getEntityCode());
3351

    
3352
            status.message("Revert completed");
3353
            status.terminate();
3354
            return ERR_NO_ERROR;
3355
        } catch (Exception ex) {
3356
            LOGGER.warn("Can't revert changes.", ex);
3357
            status.message("Can't revert changes");
3358
            status.abort();
3359
            return ERR_CANT_REVERT;
3360
        } finally {
3361
            DisposeUtils.disposeQuietly(transaction);
3362
        }
3363
    }
3364
    
3365
    @Override
3366
    public int export(String entityName, String tableName, String revisionCode, Timestamp efectiveDate, SimpleTaskStatus status) {
3367
        FeatureStore target = null;
3368
        FeatureStore entitiesStore = null;
3369
        int errcode = ERR_OK;
3370
        VCSGisCheckoutRequest request = null;
3371
        if (status == null) {
3372
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("_Export");
3373
            status.setAutoremove(true);
3374
            status.add();
3375
        }
3376
        try {
3377
            LOGGER.debug("===: EXPORT " + this.getCode() + ", '" + this.getLabel() + "', " + tableName);
3378
            status.message("Preparing export");
3379
            VCSGisEntity lentity = this.getEntity(entityName);
3380
            if (lentity == null) {
3381
                status.message("Table " + tableName + " not exists");
3382
                status.abort();
3383
                return ERR_ENTITY_NOT_EXISTS;
3384
            }
3385
            reloadRepositoryEntities(status);
3386
            request = this.getRepository().createCheckoutRequest(entityName);
3387
            request.setAuthenticationToken(this.authenticationToken);
3388
            request.setUserCode(this.currentUser);
3389
            request.setEfectiveDate(efectiveDate);
3390
            request.setRevisionCode(revisionCode);
3391

    
3392
            status.message("Executing export request for " + tableName);
3393
            if ( execute(request) != ERR_OK) {
3394
                status.message("Can't export " + tableName + " (error " + request.getLastErrorCode() + ")");
3395
                status.abort();
3396
                return request.getLastErrorCode();
3397
            }
3398
            status.message("Updating " + tableName + " metadata");
3399
            VCSGisEntity rentity = request.getEntity();
3400
//            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
3401
//            entitiesStore.edit(FeatureStore.MODE_FULLEDIT);
3402
//            VCSGisEntity rentity = request.getEntity();
3403
//            lentity = new EntityRow(this);
3404
//            rentity.copyto(lentity);
3405
//            lentity.insert(entitiesStore);
3406
//            LOGGER.debug("===: CHECKOUT " + this.getCode() + ", '" + this.getLabel() + "', " + tableName + ", rev." + rentity.getRepositoryRevisionCode());
3407

    
3408
//            this.forceReloadWorkspaceEntities();
3409
            status.message("Creating table " + tableName);
3410
            this.create_table(lentity, tableName);
3411

    
3412
            status.message("Adding features in " + tableName);
3413
            errcode = ERR_CANT_OPEN_STORE;
3414
            target = this.openFeatureStore(tableName);
3415
            this.addStoreIgnoreChanges(target);
3416
            DisposableIterable<VCSGisRepositoryData> data = request.getData();
3417
//            long sz = ContainerUtils.size64(data); // Con tablas tochas esto deja frita la app.
3418
//            status.setRangeOfValues(0, sz);
3419
            status.setCurValue(0);
3420
            errcode = ERR_CANT_INSERT_FEATURES;
3421
            target.edit(FeatureStore.MODE_APPEND);
3422
            for (VCSGisRepositoryData d : data) {
3423
                EditableFeature f = target.createNewFeature(d.getDataAsJson());
3424
                target.insert(f);
3425
                status.incrementCurrentValue();
3426
            }
3427
            target.finishEditing();
3428

    
3429
            status.message("Updating " + tableName + " metadata");
3430
//            if(StringUtils.isBlank(revisionCode)){
3431
//                lentity.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
3432
//            } else {
3433
//                lentity.setLocalRevisionCode(revisionCode);
3434
//            }
3435
//            lentity.update(entitiesStore);
3436
//            entitiesStore.finishEditing();
3437
//            this.forceReloadWorkspaceEntities();
3438
            request.dispose();
3439

    
3440
            status.message("Export completed");
3441
            status.terminate();
3442
            return ERR_NO_ERROR;
3443
        } catch (Exception ex) {
3444
            LOGGER.warn("Can't export.", ex);
3445
            status.message("Can't export");
3446
            status.abort();
3447
            if (target != null) {
3448
                target.cancelEditingQuietly();
3449
            }
3450
            if (entitiesStore != null) {
3451
                entitiesStore.cancelEditingQuietly();
3452
            }
3453
            return errcode;
3454
        } finally {
3455
            DisposeUtils.disposeQuietly(request);
3456
            if (target != null) {
3457
                this.removeStoreIgnoreChanges(target);
3458
            }
3459
            DisposeUtils.disposeQuietly(target);
3460
            DisposeUtils.disposeQuietly(entitiesStore);
3461

    
3462
        }
3463
    }
3464
}