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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
487
    }
488

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

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

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

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

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

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

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

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

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

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

    
675
                }
676

    
677
                return ERR_OK;
678
            }
679

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
838
            this.create_table(entity);
839

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

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

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

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

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

    
992
    }
993

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1172
            entity = this.getWorkspaceEntityByName(name);
1173

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

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

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

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

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

    
1212
            target.finishEditing();
1213

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

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

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

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

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

    
1246
            entitiesStore.edit(MODE_FULLEDIT);
1247

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

    
1251
            entitiesStore.finishEditing();
1252

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

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

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

    
1281
        };
1282
        return changes;
1283
    }
1284

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

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

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

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

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

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

    
1377
        };
1378
        return changes;
1379
    }
1380

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

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

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

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

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

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

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

    
1481
        LOGGER.debug("===: COMMIT: Adding changed local entities");
1482
        status.message("Searching changed entities");
1483

    
1484
        VCSGisWorkspaceEntity localEntity = this.getWorkspaceEntity(entity);
1485
        request.add(request.createEntity(localEntity));
1486

    
1487
        LOGGER.debug("===: COMMIT: Mark new local entities");
1488
        status.message("Searching new entities");
1489

    
1490
        // Marcamos como nuevas las entidades que se han dado de alta.
1491
        DisposableFeatureSetIterable changesOfAddEntities = changesTable.getByOperation(this, localEntity.getEntityCode(), OP_ADD_ENTITY);
1492
        for (Feature fchange : changesOfAddEntities) {
1493
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1494
            if (change.isSelected()) {
1495
                request.markAsNew(change.getEntity());
1496
            }
1497
        }
1498
        changesOfAddEntities.dispose();
1499

    
1500
        LOGGER.debug("===: COMMIT: Adding data");
1501
        status.message("Searching changed data");
1502
        // adicionamos los datos
1503
        boolean useSeleccion = true;
1504

    
1505
        DisposableFeatureSetIterable changes = changesTable.getSelectedsWithoutAddEntity(this, localEntity.getEntityCode());
1506
        if (changes != null) {
1507
            request.add(new DisposableIterableAdapter(
1508
                    changes,
1509
                    new DisposableIterableAdapter.ItemConverter<Feature, VCSGisChange>() {
1510
                @Override
1511
                public VCSGisChange convert(Feature f) {
1512
                    return new WorkspaceChangeRow(VCSGisWorkspaceImpl.this, f);
1513
                }
1514
            }
1515
            )
1516
            );
1517
        }
1518
        if (isMyStatus) {
1519
            status.terminate();
1520
        }
1521
        return useSeleccion;
1522
    }
1523

    
1524
    @Override
1525
    public boolean canCommit() {
1526
        return canCommit(null);
1527
    }
1528

    
1529
    @Override
1530
    public boolean canCommit(MutableObject<String> message) {
1531

    
1532
        List<String> entityNames = new ArrayList<>();
1533
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1534
        DisposableFeatureSetIterable changesGroupedByEntity = null;
1535
        try {
1536

    
1537
            changesGroupedByEntity = changesTable.getGroupedByEntity(this);
1538
            for (Feature fchange : changesGroupedByEntity) {
1539
                WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1540
                VCSGisWorkspaceEntity entity = change.getEntity();
1541
                LOGGER.debug("===: CAN-COMMIT: add used entity = " + fchange.toJson().toString().replace('\n', ' '));
1542
                if (change.isSelected() && entity.isOutdated()) {
1543
                    entityNames.add(entity.getEntityName());
1544
                }
1545
            }
1546
            DisposeUtils.dispose(changesGroupedByEntity);
1547

    
1548
            if (!entityNames.isEmpty()) {
1549
                if (message != null) {
1550
                    I18nManager i18n = ToolsLocator.getI18nManager();
1551
                    String msg = i18n.getTranslation("_Tables_in_working_copy_are_outdated")
1552
                            + ". ("
1553
                            + StringUtils.join(entityNames, ", ")
1554
                            + ")";
1555
                    message.setValue(msg);
1556
                }
1557
                return false;
1558
            }
1559
            return true;
1560
        } catch (Exception ex) {
1561
            return false;
1562
        } finally {
1563
            DisposeUtils.dispose(changesGroupedByEntity);
1564
        }
1565
    }
1566

    
1567
    @Override
1568
    public List<VCSGisWorkspaceEntity> getEntitiesWithChanges() {
1569

    
1570
        List<VCSGisWorkspaceEntity> entities = new ArrayList<>();
1571
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1572
        DisposableFeatureSetIterable changesGroupedByEntity = null;
1573
        try {
1574

    
1575
            changesGroupedByEntity = changesTable.getGroupedByEntity(this);
1576
            for (Feature fchange : changesGroupedByEntity) {
1577
                WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1578
                VCSGisWorkspaceEntity entity = change.getEntity();
1579
                if (change.isSelected()) {
1580
                    entities.add(entity);
1581
                }
1582
            }
1583
            return entities;
1584

    
1585
        } catch (Exception ex) {
1586
            return null;
1587
        } finally {
1588
            DisposeUtils.dispose(changesGroupedByEntity);
1589
        }
1590
    }
1591

    
1592
    @Override
1593
    public int commit() {
1594
        return commit(null, now(), null, null);
1595
    }
1596

    
1597
    @Override
1598
    public int commit(Timestamp efectivedate, String comment, SimpleTaskStatus status) {
1599
        return commit(null, efectivedate, comment, status);
1600
    }
1601

    
1602
    @Override
1603
    @SuppressWarnings("Convert2Lambda")
1604
    public int commit(Timestamp revisiondate, Timestamp efectivedate, String comment, SimpleTaskStatus status) {
1605
        VCSGisCommitRequest request = null;
1606
        if (status == null) {
1607
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Commit");
1608
            status.setAutoremove(true);
1609
            status.add();
1610
        }
1611
        try {
1612
            LOGGER.debug("===: COMMIT " + this.getCode() + ", " + this.getLabel());
1613
            EntitiesTable entitiesTable = new EntitiesTable();
1614
            WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1615

    
1616
            status.message("Preparing commit");
1617
            reloadRepositoryEntities(status);
1618
            request = this.getRepository().createCommitRequest();
1619
            request.setAuthenticationToken(this.authenticationToken);
1620
            request.setUserCode(this.currentUser);
1621

    
1622
            boolean useSeleccion = this.prepareCommitRequest(request, revisiondate, efectivedate, comment, status);
1623

    
1624
            LOGGER.debug("===: COMMIT: Do execute request");
1625
            status.message("Executing commit request");
1626
            if ( execute(request) != ERR_OK) {
1627
                status.message("Can't commit changes (error " + request.getLastErrorCode() + ")");
1628
                status.abort();
1629
                return request.getLastErrorCode();
1630
            }
1631

    
1632
            LOGGER.debug("===: COMMIT: update local entities table");
1633
            status.message("Updating local metadata");
1634
            FeatureStore entitiesStore = null;
1635
            try {
1636
                entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1637
                entitiesStore.edit(FeatureStore.MODE_FULLEDIT);
1638
                List<VCSGisWorkspaceEntity> changedLocalentities = request.getChangedLocalEntities();
1639
                status.setRangeOfValues(0, changedLocalentities.size());
1640
                status.setCurValue(0);
1641
                for (VCSGisEntity rentity : changedLocalentities) {
1642
                    EntityRow entityRow = entitiesTable.getByEntityName(this, rentity.getEntityName());
1643
                    if (entityRow != null) {
1644
                        entityRow.copyfrom(rentity);
1645
                        entityRow.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
1646
                        entityRow.update(entitiesStore);
1647
                    }
1648
                    status.incrementCurrentValue();
1649
                }
1650
                entitiesStore.finishEditing();
1651
                forceReloadWorkspaceEntities();
1652
            } catch (Exception e) {
1653
                FeatureStore.cancelEditingQuietly(entitiesStore);
1654
            } finally {
1655
                DisposeUtils.disposeQuietly(entitiesStore);
1656
                entitiesStore = null;
1657
            }
1658

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

    
1691
            status.message("Preparing commit");
1692
            reloadRepositoryEntities(status);
1693
            request = this.getRepository().createCommitRequest();
1694
            request.setAuthenticationToken(this.authenticationToken);
1695
            request.setUserCode(this.currentUser);
1696

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

    
1699
            LOGGER.debug("===: COMMIT: Do execute request");
1700
            status.message("Executing commit request");
1701
            if ( execute(request) != ERR_OK) {
1702
                status.message("Can't commit changes (error " + request.getLastErrorCode() + ")");
1703
                status.abort();
1704
                return request.getLastErrorCode();
1705
            }
1706

    
1707
            LOGGER.debug("===: COMMIT: update local entities table");
1708
            status.message("Updating local metadata");
1709
            FeatureStore entitiesStore = null;
1710
            try {
1711
                entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1712
                entitiesStore.edit(FeatureStore.MODE_FULLEDIT);
1713
                List<VCSGisWorkspaceEntity> changedLocalentities = request.getChangedLocalEntities();
1714
                status.setRangeOfValues(0, changedLocalentities.size());
1715
                status.setCurValue(0);
1716
                for (VCSGisWorkspaceEntity rentity : changedLocalentities) {
1717
                    EntityRow entityRow = entitiesTable.getByEntityName(this, rentity.getEntityName());
1718
                    if (entityRow != null) {
1719
                        entityRow.copyfrom(rentity);
1720
                        entityRow.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
1721
                        entityRow.update(entitiesStore);
1722
                    }
1723
                    status.incrementCurrentValue();
1724
                }
1725
                entitiesStore.finishEditing();
1726
                forceReloadWorkspaceEntities();
1727
            } catch (Exception e) {
1728
                FeatureStore.cancelEditingQuietly(entitiesStore);
1729
            } finally {
1730
                DisposeUtils.disposeQuietly(entitiesStore);
1731
                entitiesStore = null;
1732
            }
1733

    
1734
            LOGGER.debug("===: COMMIT: clean local changes");
1735
            status.message("Removing local list of changes");
1736
            if (useSeleccion) {
1737
                changesTable.deleteSelecteds(this);
1738
            } else {
1739
                changesTable.deleteAll(this);
1740
            }
1741
            status.message("Commit completed");
1742
            status.terminate();
1743
            return ERR_NO_ERROR;
1744
        } catch (Exception ex) {
1745
            LOGGER.warn("Can't commit changes.", ex);
1746
            status.message("Can't commit changes");
1747
            status.abort();
1748
            return ERR_CANT_COMMIT;
1749
        } finally {
1750
            DisposeUtils.disposeQuietly(request);
1751
        }
1752
        
1753
    }
1754

    
1755

    
1756
    @Override
1757
    public int checkout(String tableName) {
1758
        return checkout(tableName, null);
1759
    }
1760

    
1761
    @Override
1762
    public int checkout(String tableName, String revisionCode) {
1763
        return checkout(tableName, revisionCode, null);
1764
    }
1765

    
1766
    @Override
1767
    public int checkout(String tableName, String revisionCode, SimpleTaskStatus status) {
1768
        FeatureStore target = null;
1769
        FeatureStore entitiesStore = null;
1770
        int errcode = ERR_OK;
1771
        VCSGisCheckoutRequest request = null;
1772
        if (status == null) {
1773
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("_Checkout");
1774
            status.setAutoremove(true);
1775
            status.add();
1776
        }
1777
        try {
1778
            LOGGER.debug("===: CHECKOUT " + this.getCode() + ", '" + this.getLabel() + "', " + tableName);
1779
            status.message("Preparing checkout");
1780
            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
1781
            if (lentity != null) {
1782
                status.message("Table " + tableName + " already exists");
1783
                status.abort();
1784
                return ERR_ENTITY_ALREADY_EXISTS;
1785
            }
1786
            reloadRepositoryEntities(status);
1787
            request = this.getRepository().createCheckoutRequest(tableName);
1788
            request.setAuthenticationToken(this.authenticationToken);
1789
            request.setUserCode(this.currentUser);
1790
            request.setEfectiveDate((Timestamp) null);
1791
            request.setRevisionCode(revisionCode);
1792

    
1793
            status.message("Executing checkout request for " + tableName);
1794
            if ( execute(request) != ERR_OK) {
1795
                status.message("Can't checkout " + tableName + " (error " + request.getLastErrorCode() + ")");
1796
                status.abort();
1797
                return request.getLastErrorCode();
1798
            }
1799
            status.message("Updating " + tableName + " metadata");
1800
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1801
            entitiesStore.edit(FeatureStore.MODE_FULLEDIT);
1802
            VCSGisEntity rentity = request.getEntity();
1803
            lentity = new EntityRow(this);
1804
            rentity.copyto(lentity);
1805
            lentity.insert(entitiesStore);
1806
            LOGGER.debug("===: CHECKOUT " + this.getCode() + ", '" + this.getLabel() + "', " + tableName + ", rev." + rentity.getRepositoryRevisionCode());
1807

    
1808
//            this.forceReloadWorkspaceEntities();
1809
            status.message("Creating table " + tableName);
1810
            this.create_table(lentity);
1811

    
1812
            status.message("Adding features in " + tableName);
1813
            errcode = ERR_CANT_OPEN_STORE;
1814
            target = this.openFeatureStore(lentity);
1815
            this.addStoreIgnoreChanges(target);
1816
            DisposableIterable<VCSGisRepositoryData> data = request.getData();
1817
//            long sz = ContainerUtils.size64(data); // Con tablas tochas esto deja frita la app.
1818
//            status.setRangeOfValues(0, sz);
1819
            status.setCurValue(0);
1820
            errcode = ERR_CANT_INSERT_FEATURES;
1821
            target.edit(FeatureStore.MODE_APPEND);
1822
            for (VCSGisRepositoryData d : data) {
1823
                EditableFeature f = target.createNewFeature(d.getDataAsJson());
1824
                target.insert(f);
1825
                status.incrementCurrentValue();
1826
            }
1827
            target.finishEditing();
1828

    
1829
            status.message("Updating " + tableName + " metadata");
1830
            if(StringUtils.isBlank(revisionCode)){
1831
                lentity.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
1832
            } else {
1833
                lentity.setLocalRevisionCode(revisionCode);
1834
            }
1835
            lentity.update(entitiesStore);
1836
            entitiesStore.finishEditing();
1837
            this.forceReloadWorkspaceEntities();
1838
            request.dispose();
1839

    
1840
            status.message("Checkout completed");
1841
            status.terminate();
1842
            return ERR_NO_ERROR;
1843
        } catch (Exception ex) {
1844
            LOGGER.warn("Can't checkout.", ex);
1845
            status.message("Can't checkout");
1846
            status.abort();
1847
            if (target != null) {
1848
                target.cancelEditingQuietly();
1849
            }
1850
            if (entitiesStore != null) {
1851
                entitiesStore.cancelEditingQuietly();
1852
            }
1853
            return errcode;
1854
        } finally {
1855
            DisposeUtils.disposeQuietly(request);
1856
            if (target != null) {
1857
                this.removeStoreIgnoreChanges(target);
1858
            }
1859
            DisposeUtils.disposeQuietly(target);
1860
            DisposeUtils.disposeQuietly(entitiesStore);
1861

    
1862
        }
1863
    }
1864

    
1865
    @Override
1866
    public int updateEntitiesFromRepository() {
1867
        return this.updateEntitiesFromRepository(null);
1868
    }
1869

    
1870
    @Override
1871
    public int updateEntitiesFromRepository(SimpleTaskStatus status) {
1872
        LOGGER.debug("===: UPDATE_ENTITIES " + this.getCode() + ", '" + this.getLabel() + "'");
1873
        FeatureStore entitiesStore = null;
1874
        EntitiesTable entitiesTable = new EntitiesTable();
1875
        if (status == null) {
1876
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Update metadata tables");
1877
            status.setAutoremove(true);
1878
            status.add();
1879
        }
1880
        try {
1881
            status.message("Preparing update metadata tables");
1882
            this.reloadRepositoryEntities(status);
1883

    
1884
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1885
            entitiesStore.edit(MODE_FULLEDIT);
1886
            for (VCSGisEntity rentity : this.getRepositoryEntities()) {
1887
                EntityRow entityRow = entitiesTable.getByEntityName(this, rentity.getEntityName());
1888
                if (entityRow != null) {
1889
                    rentity.copyto(entityRow);
1890
                    entityRow.update(entitiesStore);
1891
                }
1892
            }
1893
            entitiesStore.finishEditingQuietly();
1894

    
1895
            this.reloadWorkspaceEntities();
1896
            status.message("Update metadata tables completed");
1897
            status.terminate();
1898
            return ERR_OK;
1899
        } catch (Exception ex) {
1900
            LOGGER.warn("Can't update metadata tables.", ex);
1901
            status.message("Can't update metadata tables");
1902
            status.abort();
1903
            if (entitiesStore != null) {
1904
                entitiesStore.cancelEditingQuietly();
1905
            }
1906
            return ERR_CANT_UPDATE_ENTITIES;
1907
        } finally {
1908
            DisposeUtils.disposeQuietly(entitiesStore);
1909
            entitiesStore = null;
1910
        }
1911
    }
1912

    
1913
    @Override
1914
    public int updatePrepare(String tableName) {
1915
        return updatePrepare(tableName, null);
1916
    }
1917

    
1918
    @Override
1919
    public int updatePrepare(String tableName, SimpleTaskStatus status) {
1920
        LOGGER.debug("===: UPDATE_PREPARE: " + tableName + " WS " + this.getCode() + ", '" + this.getLabel() + "'");
1921
        if (status == null) {
1922
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Update-prepare " + tableName);
1923
            status.setAutoremove(true);
1924
            status.add();
1925
        }
1926

    
1927
        FeatureStore remoteChangesStore = null;
1928
        VCSGisUpdateRequest request = null;
1929
        DisposableIterable<VCSGisRepositoryData> remoteChanges = null;
1930
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1931
        FeatureStore userStore = null;
1932
        FeatureStore localChangesStore = null;
1933
        FeatureStore entitiesStore = null;
1934
        DataTransaction transaction = null;
1935
        try {
1936
            transaction = DALLocator.getDataManager().createTransaction();
1937
            transaction.begin();
1938
            transaction.add(this.getExplorer(), false);
1939

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

    
1975
            status.message("Preparing remote changes container");
1976
            remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
1977
            transaction.add(remoteChangesStore);
1978
            remoteChangesStore.edit(MODE_PASS_THROUGH);
1979

    
1980
            status.message("Deleting previous temporary remote changes");
1981
            LOGGER.debug("===: UPDATE_PREPARE: Delete updates table");
1982
            remoteChangesStore.delete("\"" + COD_ENTITY + "\"='" + entityCode + "'");
1983

    
1984
            remoteChanges = request.getData();
1985
            transaction.add(remoteChanges);
1986
//            long sz = ContainerUtils.size64(remoteChanges);
1987
//            status.setRangeOfValues(0, sz);
1988
            status.setCurValue(0);
1989

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

    
2021
                if (hasConflictRemoteChangeWithUserTable(lentity, remoteChange, userStore)) {
2022
                    remoteChangeRow.setStatus(STATE_CONFLICT);
2023
                    lentity.setState(STATE_CONFLICT);
2024
                }
2025

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

    
2069
                }
2070
                remoteChangeRow.insert(remoteChangesStore);
2071
                status.incrementCurrentValue();
2072
            }
2073
            LOGGER.debug("===: UPDATE_PREPARE: finish inserting updates");
2074
            lentity.update(entitiesStore);
2075

    
2076
            remoteChangesStore.finishEditing();
2077
            localChangesStore.finishEditing();
2078
            entitiesStore.finishEditing();
2079

    
2080
            updateLocallyModyfiedRemoteChanges();
2081

    
2082
            transaction.commit();
2083

    
2084
            status.message("Update-prepare completed");
2085
            status.terminate();
2086
            return ERR_OK;
2087
        } catch (Exception ex) {
2088
            LOGGER.warn("Can't prepare update.", ex);
2089
            status.message("Can't prepare update");
2090
            status.abort();
2091
            DataTransaction.rollbackQuietly(transaction);
2092
            return ERR_CANT_PREPARE_UPDATE;
2093
        } finally {
2094
            DisposeUtils.disposeQuietly(transaction);
2095
        }
2096

    
2097
    }
2098

    
2099
    private void updateLocallyModyfiedRemoteChanges() {
2100

    
2101
        RemoteChangesTable changes = new RemoteChangesTable();
2102
        changes.updateStateFromLocalChanges(this, STATE_LOCAL_OUTDATED_AND_MODIFIED);
2103

    
2104
    }
2105

    
2106
    private boolean hasConflictRemoteChangeWithUserTable(VCSGisEntity lentity, VCSGisRepositoryData remoteChange, FeatureStore store) throws DataException {
2107
        if (store != null) {
2108
            FeatureType featType = lentity.getFeatureType();
2109
            JsonObject data = remoteChange.getDataAsJson();
2110
            ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
2111
            ExpressionBuilder builder = expManager.createExpressionBuilder();
2112
            builder.set(null);
2113
            for (FeatureAttributeDescriptor attr : featType) {
2114
                if (attr.isIndexed() && !attr.allowIndexDuplicateds()) {
2115
                    Object value = Json.toObject(data, attr.getName());
2116
                    builder.and(
2117
                            builder.eq(
2118
                                    builder.column(attr.getName()),
2119
                                    builder.constant(value)
2120
                            )
2121
                    );
2122

    
2123
                    Feature f = store.findFirst(builder.toString());
2124
                    if (f != null && !StringUtils.equals(
2125
                            f.getString(lentity.getFeatureIdFieldName()),
2126
                            remoteChange.getFeatureRelatedCode())) {
2127
                        return true;
2128
                    }
2129
                }
2130
            }
2131
        }
2132
        return false;
2133
    }
2134

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

    
2200
        FeatureSet feats = store.getFeatureSet(filter.toString());
2201
        return feats.iterable();
2202
    }
2203

    
2204
    @Override
2205
    public int updateClean(String entityCode) {
2206
        return updateClean(entityCode, null);
2207
    }
2208

    
2209
    @Override
2210
    public int updateClean(String entityCode, SimpleTaskStatus status) {
2211
        VCSGisEntity entity = this.getEntity(entityCode);
2212
        if (entity == null) {
2213
            return ERR_ENTITY_NOT_EXISTS;
2214
        }
2215
        if (status == null) {
2216
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2217
                    "Update-clean " + entity.getEntityName()
2218
            );
2219
            status.setAutoremove(true);
2220
            status.add();
2221
        }
2222
        try {
2223
            status.message("Deleting temporary remote changes (" + entity.getEntityName() + ")");
2224
            RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2225
            remoteChangesTable.delete(this, entityCode);
2226
            status.message("Delete temporary remote changes completed");
2227
            status.terminate();
2228
            return ERR_OK;
2229
        } catch (Exception ex) {
2230
            LOGGER.warn("Can't deleting temporary remote changes of " + entity.getEntityName() + ".", ex);
2231
            status.message("Can't deleting temporary remote changes of " + entity.getEntityName() + ".");
2232
            status.abort();
2233
            return ERR_CANT_UPDATE_CLEAN;
2234
        }
2235

    
2236
    }
2237

    
2238
    @Override
2239
    public int update(String tableName) {
2240
        return this.update(tableName, false, false, null);
2241
    }
2242

    
2243
    @Override
2244
    public int update(String tableName, SimpleTaskStatus status) {
2245
        return this.update(tableName, false, false, status);
2246
    }
2247

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

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

    
2258
    public int update(String tableName, boolean prepare, boolean merge, SimpleTaskStatus status) {
2259
        int errcode = ERR_NO_ERROR;
2260
        if (status == null) {
2261
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2262
                    "Update " + tableName
2263
            );
2264
            status.setAutoremove(true);
2265
            status.add();
2266
        }
2267
        if (prepare) {
2268
            errcode = this.updatePrepare(tableName, status);
2269
            if (errcode != ERR_OK) {
2270
                return errcode;
2271
            }
2272
        }
2273
        LOGGER.debug("===: UPDATE " + this.getCode() + ", '" + this.getLabel() + "', " + tableName);
2274
        RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2275
        WorkspaceChangesTable localChangesTable = new WorkspaceChangesTable();
2276

    
2277
        EditableFeature ef;
2278
        DisposableFeatureSetIterable remoteChanges = null;
2279

    
2280
        FeatureStore workspaceChangesStore = null;
2281
        FeatureStore remoteChangesStore = null;
2282
        FeatureStore userStore = null;
2283
        FeatureStore entitiesStore = null;
2284

    
2285
        DataTransaction transaction = null;
2286
        try {
2287
            transaction = DALLocator.getDataManager().createTransaction();
2288
            transaction.begin();
2289

    
2290
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
2291
            transaction.add(entitiesStore);
2292
            entitiesStore.edit(MODE_PASS_THROUGH);
2293

    
2294
            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
2295
            if (lentity == null) {
2296
                lentity = new EntityRow(this);
2297
                VCSGisEntity rentity = this.getRepositoryEntityByName(tableName);
2298
                lentity.copyfrom(rentity);
2299
                lentity.setLocalRevisionCode(null);
2300
                lentity.update(entitiesStore);
2301
            }
2302
            if (!merge) {
2303
                status.message("Checking the need to merge");
2304
                if (remoteChangesTable.updateNeedMerge(this, lentity.getEntityCode())) {
2305
                    status.message("Can't update without merge.");
2306
                    status.abort();
2307
                    return ERR_UPDATE_NEED_MERGE;
2308
                }
2309
            }
2310
            String dataCodeFieldName = lentity.getFeatureIdFieldName();
2311
            status.message("Searching remote changes (" + lentity.getEntityName() + ")");
2312

    
2313
            userStore = this.openFeatureStore(lentity);
2314
            if (userStore == null) {
2315
                this.create_table(lentity);
2316
                userStore = this.openFeatureStore(lentity);
2317
            }
2318
            transaction.add(userStore);
2319
            userStore.edit(MODE_PASS_THROUGH);
2320

    
2321
            workspaceChangesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
2322
            transaction.add(workspaceChangesStore);
2323
            workspaceChangesStore.edit(MODE_PASS_THROUGH);
2324

    
2325
            remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
2326
            transaction.add(remoteChangesStore);
2327
            remoteChangesStore.edit(MODE_PASS_THROUGH);
2328

    
2329
            remoteChanges = remoteChangesTable.getSelectedsByEntityCodeAsIterator(this, lentity.getCode());
2330
            transaction.add(remoteChanges);
2331
//            long sz = ContainerUtils.size64(remoteChanges);
2332
//            status.setRangeOfValues(0, sz);
2333
            status.setCurValue(0);
2334

    
2335
            if (!remoteChanges.isEmpty()) {
2336
                this.addStoreIgnoreChanges(userStore);
2337
                status.message("Updating table (" + lentity.getEntityName() + ")");
2338
                FeatureType type = userStore.getDefaultFeatureTypeQuietly();
2339

    
2340
                ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
2341
                ExpressionBuilder builder = expManager.createExpressionBuilder();
2342

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

    
2403
                        case OP_DELETE:
2404
                            LOGGER.debug("===: UPDATE: delete");
2405
                            userStore.delete("\"" + dataCodeFieldName + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2406
//                            workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\"='" + remoteChangeRow.getRelatedFeatureCode()+ "'");
2407
                            break;
2408
                    }
2409
                    status.incrementCurrentValue();
2410
                }
2411
            }
2412

    
2413
            if (merge) {
2414
                status.message("Searching local changes to merge (" + lentity.getEntityName() + ")");
2415
                DisposeUtils.disposeQuietly(remoteChanges);
2416
                remoteChanges = remoteChangesTable.getNotSelectedsByEntityCodeAsIterator(this, lentity.getCode());
2417
                transaction.add(remoteChanges);
2418
//                sz = ContainerUtils.size64(remoteChanges);
2419
//                status.setRangeOfValues(0, sz);
2420
                status.setCurValue(0);
2421

    
2422
                if (!remoteChanges.isEmpty()) {
2423
                    //We edit the changesStore because we will need local changes 
2424
//                    workspaceChangesStore.edit(MODE_PASS_THROUGH);
2425

    
2426
                    //We edit the destination store because we may need to update some features (in case OP_DELETE)
2427
//                    userStore.edit(MODE_PASS_THROUGH);
2428
                    this.addStoreIgnoreChanges(userStore);
2429

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

    
2444
                            case OP_UPDATE:
2445
                                LOGGER.debug("===: UPDATE: update");
2446
                                if (f == null) {
2447
                                    this.addDeleteChange(lentity, workspaceChangesStore, remoteChangeRow.getRelatedFeatureCode(), null, null);
2448
                                } else {
2449
                                    this.addChange(lentity, OP_UPDATE, workspaceChangesStore, f, null);
2450
                                }
2451
                                break;
2452
                            case OP_DELETE:
2453
                                LOGGER.debug("===: UPDATE: delete");
2454
                                if (f != null) {
2455
                                    userStore.delete("\"" + dataCodeFieldName + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2456

    
2457
                                    ef = userStore.createNewFeature(f);
2458
                                    ef.setString(lentity.getFeatureIdFieldName(), this.createUniqueCode());
2459
                                    userStore.insert(ef);
2460

    
2461
                                    workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2462
                                    this.addChange(lentity, OP_INSERT, workspaceChangesStore, ef, null);
2463

    
2464
                                }
2465
                                break;
2466
                        }
2467
                        status.incrementCurrentValue();
2468
                    }
2469
                }
2470
            }
2471
            localChangesTable.removeLocalChangesRelatedToSelectedRemoteChanges(this, lentity);
2472
            remoteChangesTable.delete(remoteChangesStore, lentity.getEntityCode());
2473

    
2474
            status.message("Updating metadata tables");
2475
            lentity.setLocalRevisionCode(lentity.getRepositoryRevisionCode());
2476
            lentity.update(entitiesStore);
2477
            forceReloadWorkspaceEntities();
2478

    
2479
            transaction.commit();
2480

    
2481
            status.message("Update completed");
2482
            status.terminate();
2483
            return ERR_OK;
2484
        } catch (Exception ex) {
2485
            LOGGER.warn("Can't update.", ex);
2486
            status.message("Can't update");
2487
            status.abort();
2488
            return ERR_CANT_UPDATE;
2489
        } finally {
2490
            this.removeStoreIgnoreChanges(userStore);
2491
            DisposeUtils.disposeQuietly(transaction);
2492
        }
2493
    }
2494

    
2495
    @Override
2496
    public JDBCServerExplorer getExplorer() {
2497
        return this.wsexplorer;
2498
    }
2499

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

    
2633
            Map<String, VCSGisEntity> tmp = new HashMap<>();
2634
            entities.forEach(entity -> {
2635
                tmp.put(entity.getEntityCode(), entity);
2636
            });
2637
            this.repositoryEntitiesByCode = tmp;
2638
            
2639
            Map<String, EntityRow> theEntitiesByName = new HashMap<>();
2640
            Map<String, EntityRow> theEntitiesByCode = new HashMap<>();
2641

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

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

    
2686
    private boolean hasRepositoryEntities() {
2687
        return this.repositoryEntitiesByCode != null;
2688
    }
2689
    
2690
    @Override
2691
    public List<VCSGisEntity> getRepositoryEntities() {
2692
        if (this.repositoryEntitiesByCode == null) {
2693
            reloadRepositoryEntities(null);
2694
        }
2695
        List<VCSGisEntity> entities = new ArrayList<>(this.repositoryEntitiesByCode.values());
2696
        return entities;
2697
    }
2698

    
2699
    @Override
2700
    public boolean updateNeedMerge(String entityName) {
2701
        RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2702

    
2703
        VCSGisEntity entity = this.getWorkspaceEntity(entityName);
2704
        if (entity == null) {
2705
            entity = this.getRepositoryEntity(entityName);
2706
        }
2707

    
2708
        return remoteChangesTable.updateNeedMerge(this, entity.getEntityCode());
2709
    }
2710

    
2711
    @Override
2712
    public void addToConnectionPool() {
2713
        JDBCServerExplorerParameters params = this.getExplorerParameters();
2714
        DataManager dataManager = DALLocator.getDataManager();
2715
        dataManager.getDataServerExplorerPool().add(this.getLabel(), params);
2716
    }
2717

    
2718
    @Override
2719
    public boolean isInMyDatabase(FeatureStore store) {
2720
        if (!(store.getParameters() instanceof JDBCStoreParameters)) {
2721
            return false;
2722
        }
2723
        JDBCStoreParameters storeParams = (JDBCStoreParameters) store.getParameters();
2724
        JDBCServerExplorerParameters explorerParams = this.getExplorerParameters();
2725
        if (!StringUtils.equalsIgnoreCase(storeParams.getProviderName(), explorerParams.getProviderName())) {
2726
            return false;
2727
        }
2728
        return StringUtils.equalsIgnoreCase(storeParams.getUrl(), explorerParams.getUrl());
2729
    }
2730

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

    
2754
            VCSGisEntity lentity = this.getEntity(entityName);
2755
            if (lentity == null) {
2756
                status.message("Can't find table '" + entityName + "'");
2757
                status.abort();
2758
                return ERR_ENTITY_NOT_EXISTS;
2759
            }
2760

    
2761
            status.message("Executing history request");
2762
            VCSGisHistoryRequest request = this.getRepository().createHistoryRequest(entityName);
2763
            transaction.add(request);
2764

    
2765
            request.setAuthenticationToken(this.authenticationToken);
2766
            request.setUserCode(this.currentUser);
2767
            request.setDateRange(minDate, maxDate);
2768
            request.setMaxNumberOfRevisions(maxNumberOfRevisions);
2769
            request.setRevisionNumberRange(-1, -1);
2770

    
2771
            if ( execute(request) != ERR_OK) {
2772
                status.message("Can't retriev history of " + entityName + " (error " + request.getLastErrorCode() + ")");
2773
                status.abort();
2774
                return request.getLastErrorCode();
2775
            }
2776
            LocalRevisionsTable localRevisionsTable = new LocalRevisionsTable();
2777
            FeatureStore localRevisionsStore = this.openFeatureStore(LocalRevisionsTable.TABLE_NAME);
2778
            transaction.add(localRevisionsStore);
2779
            localRevisionsStore.edit(MODE_PASS_THROUGH);
2780

    
2781
            status.message("Deleting previous local revision information");
2782
            localRevisionsTable.deleteByEntityCodeAndGroup(
2783
                    this,
2784
                    localRevisionsStore,
2785
                    lentity.getEntityCode(),
2786
                    group
2787
            );
2788

    
2789
            DisposableIterable<VCSGisRevision> revisions = request.getRevisions();
2790
            status.message("Adding to local revisions");
2791
//            long sz = ContainerUtils.size64(revisions);
2792
//            status.setRangeOfValues(0, sz);
2793
            status.setCurValue(0);
2794

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

    
2813
            VarsTable varsTable = new VarsTable();
2814
            varsTable.set(
2815
                    this,
2816
                    "history_" + entityName + "_" + group + "_MinDate",
2817
                    minDate.toString()
2818
            );
2819
            varsTable.set(
2820
                    this,
2821
                    "history_" + entityName + "_" + group + "_MinRevision",
2822
                    String.valueOf(minRevision)
2823
            );
2824

    
2825
            transaction.commit();
2826
            status.message("History completed");
2827
            status.terminate();
2828
            return ERR_OK;
2829
        } catch (Exception ex) {
2830
            LOGGER.warn("Can't retrieve history.", ex);
2831
            transaction.rollbackQuietly();
2832
            status.message("Can't retrieve history");
2833
            status.abort();
2834
            return errcode;
2835
        } finally {
2836
            transaction.dispose();
2837
        }
2838
    }
2839

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

    
2858
            EntityRow lentity = this.getWorkspaceEntityByName(entityName);
2859
            if (lentity == null) {
2860
                status.message("Can't find table '" + entityName + "'");
2861
                status.abort();
2862
                return ERR_ENTITY_NOT_EXISTS;
2863
            }
2864
            VarsTable varsTable = new VarsTable();
2865

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

    
2868
            status.message("Executing history request");
2869
            VCSGisHistoryRequest request = this.getRepository().createHistoryRequest(entityName);
2870
            transaction.add(request);
2871

    
2872
            request.setAuthenticationToken(this.authenticationToken);
2873
            request.setUserCode(this.currentUser);
2874
            request.setDateRange(null, null);
2875
            request.setMaxNumberOfRevisions(maxNumberOfRevisions);
2876
            request.setRevisionNumberRange(-1, minRevision);
2877

    
2878
            if ( execute(request) != ERR_OK) {
2879
                status.message("Can't retriev history of " + entityName + " (error " + request.getLastErrorCode() + ")");
2880
                status.abort();
2881
                return request.getLastErrorCode();
2882
            }
2883
            FeatureStore localRevisionsStore = this.openFeatureStore(LocalRevisionsTable.TABLE_NAME);
2884
            transaction.add(localRevisionsStore);
2885
            localRevisionsStore.edit(MODE_PASS_THROUGH);
2886

    
2887
            DisposableIterable<VCSGisRevision> revisions = request.getRevisions();
2888
            status.message("Adding to local revisions");
2889
//            long sz = ContainerUtils.size64(revisions);
2890
//            status.setRangeOfValues(0, sz);
2891
            status.setCurValue(0);
2892

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

    
2913
            varsTable.set(
2914
                    this,
2915
                    "history_" + entityName + "_" + group + "_MinDate",
2916
                    minDate.toString()
2917
            );
2918
            varsTable.set(
2919
                    this,
2920
                    "history_" + entityName + "_" + group + "_MinRevision",
2921
                    String.valueOf(minRevision)
2922
            );
2923

    
2924
            transaction.commit();
2925
            status.message("history completed");
2926
            status.terminate();
2927
            return ERR_OK;
2928
        } catch (Exception ex) {
2929
            LOGGER.warn("Can't retrieve history.", ex);
2930
            transaction.rollbackQuietly();
2931
            status.message("Can't retrieve history");
2932
            status.abort();
2933
            return errcode;
2934
        } finally {
2935
            transaction.dispose();
2936
        }
2937
    }
2938

    
2939
    @Override
2940
    public GetItemWithSize64<VCSGisRevision> getRevisions(String entityName, String group) {
2941
        LocalRevisionsTable localRevisionsTable = new LocalRevisionsTable();
2942
        reloadWorkspaceEntities();
2943

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

    
2956
            @Override
2957
            public VCSGisRevision get64(long position) {
2958
                Feature f = revisionsf.get64(position);
2959
                LocalRevisionRow revision = new LocalRevisionRow(workspace, f);
2960
                return revision;
2961
            }
2962
        };
2963
        return revisions;
2964
    }
2965

    
2966
    @Override
2967
    public String getUserName(String userCode) {
2968
        return null;
2969
    }
2970

    
2971
    @Override
2972
    public VCSGisUser getUser(String userCode) {
2973
        return null;
2974
    }
2975

    
2976
    @Override
2977
    public Feature getRelatedFeature(VCSGisEntity entity, String featureCode) {
2978
        try {
2979
            FeatureStore store = this.getFeatureStore(entity.getEntityName());
2980
            Feature f = store.findFirst("\"" + entity.getFeatureIdFieldName() + "\"='" + featureCode + "'");
2981
            return f;
2982
        } catch (Exception ex) {
2983
            throw new RuntimeException("Can't retrieve feature '" + entity.getEntityName() + "/" + code + "'.", ex);
2984
        }
2985

    
2986
    }
2987

    
2988
    @Override
2989
    public Feature getRelatedFeature(VCSGisRepositoryChange change) {
2990
        EntityRow entity = this.getWorkspaceEntity(change.getEntityCode());
2991
        return getRelatedFeature(entity, change.getRelatedFeatureCode());
2992
    }
2993
    
2994
    @Override
2995
    public int removeEntity(String nameOrCode) {
2996
        int err = ERR_NO_ERROR;
2997
        EntityRow entity = this.getWorkspaceEntity(nameOrCode);
2998
        if(entity == null){
2999
            err = ERR_ENTITY_NOT_EXISTS;
3000
            return err;
3001
        }
3002

    
3003
        DataTransaction transaction = DALLocator.getDataManager().createTransaction();
3004
        try {
3005
            LOGGER.debug("===: REMOVE ENTITY " + entity.getEntityName());
3006

    
3007

    
3008
            //Eliminamos todos los cambios de esta entidad
3009
            err = ERR_CANT_REMOVE_CHANGES;
3010
            FeatureStore changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
3011
            transaction.add(changesStore);
3012
            changesStore.edit(MODE_FULLEDIT);
3013
            changesStore.delete("\""+WorkspaceChangesTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3014
            changesStore.finishEditing();
3015

    
3016
            FeatureStore remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
3017
            transaction.add(remoteChangesStore);
3018
            remoteChangesStore.edit(MODE_FULLEDIT);
3019
            remoteChangesStore.delete("\""+RemoteChangesTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3020
            remoteChangesStore.finishEditing();
3021

    
3022
            //Eliminamos las revisiones locales
3023
            FeatureStore revisionsStore = openFeatureStore(LocalRevisionsTable.TABLE_NAME);       
3024
            transaction.add(revisionsStore);
3025
            revisionsStore.edit(MODE_FULLEDIT);
3026
            revisionsStore.delete("\""+LocalRevisionsTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3027
            revisionsStore.finishEditing();
3028
            err = ERR_CANT_REMOVE_ENTITY;
3029

    
3030

    
3031
            //Eliminamos la entidad
3032
            FeatureStore entitiesStore = openFeatureStore(EntitiesTable.TABLE_NAME);       
3033
            transaction.add(entitiesStore);
3034
            entitiesStore.edit(MODE_FULLEDIT);
3035
            entitiesStore.delete("\""+EntitiesTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3036
            entitiesStore.finishEditing();
3037
            err = ERR_CANT_REMOVE_ENTITY;
3038

    
3039

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

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

    
3102
    @Override
3103
    public void setUserIdentificationRequester(VCSGisUserIdentificationRequester userIdentificationRequester) {
3104
        this.userIdentificationRequester = userIdentificationRequester;
3105
    }
3106

    
3107
    private int execute(VCSGisRequest request) {
3108
        while(true) {
3109
            switch(request.execute()) {
3110
                case ERR_CANT_AUTHENTICATE_USER:
3111
                case ERR_INVALID_AUTHENTICATION_TOKEN:
3112
                case ERR_USER_NOT_AUTHORIZED:
3113
                case ERR_AUTHENTICATION_EXPIRED:
3114
                case ERR_INVALID_USERCODE:
3115
                    if( this.userIdentificationRequester!= null ) {
3116
                        if( this.userIdentificationRequester.requestIdentification() ) {
3117
                            continue;
3118
                        }
3119
                    }
3120
                default:
3121
                    return request.getLastErrorCode();            
3122
            }
3123
        }
3124
    }
3125

    
3126

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

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

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

    
3273
//        FeatureStore entitiesStore = null;
3274

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

    
3289
            DisposableFeatureSetIterable changes = changesTable.getSelectedsByEntityCodeAsIterator(this, entity.getEntityCode());
3290
            transaction.add(changes);
3291

    
3292

    
3293
            if (!changes.isEmpty()) {
3294
                userStore = this.openFeatureStore(entity);
3295
                transaction.add(userStore, true);
3296
                userStore.edit(MODE_PASS_THROUGH);
3297
                changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
3298
                transaction.add(changesStore, true);
3299
                changesStore.edit(MODE_PASS_THROUGH);
3300

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

    
3342
//            LOGGER.debug("===: REVERT: clean local changes");
3343
//            status.message("Removing local list of changes");
3344
//            changesTable.deleteSelectedsByEntity(this, entity.getEntityCode());
3345

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

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

    
3402
//            this.forceReloadWorkspaceEntities();
3403
            status.message("Creating table " + tableName);
3404
            this.create_table(lentity, tableName);
3405

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

    
3423
            status.message("Updating " + tableName + " metadata");
3424
//            if(StringUtils.isBlank(revisionCode)){
3425
//                lentity.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
3426
//            } else {
3427
//                lentity.setLocalRevisionCode(revisionCode);
3428
//            }
3429
//            lentity.update(entitiesStore);
3430
//            entitiesStore.finishEditing();
3431
//            this.forceReloadWorkspaceEntities();
3432
            request.dispose();
3433

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

    
3456
        }
3457
    }
3458
}