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

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

    
146
/**
147
 *
148
 * @author gvSIG Teammerge
149
 */
150
@SuppressWarnings({"UseSpecificCatch", "UnusedAssignment"})
151
public class VCSGisWorkspaceImpl implements VCSGisWorkspace {
152

    
153
    private static final Logger LOGGER = LoggerFactory.getLogger(VCSGisWorkspaceImpl.class);
154

    
155
    private final Map<String, FeatureStore> storesCache;
156
    private Map<String, EntityRow> workspaceEntitiesByName;
157
    private Map<String, EntityRow> workspaceEntitiesByCode;
158
    private Map<String, VCSGisEntity> repositoryEntitiesByCode;
159
    private Set<FeatureStore> storeIgnoreChanges;
160
    private JDBCServerExplorer wsexplorer;
161
    private String code;
162
    private final VCSGisRepository repository;
163
    private final String label;
164
    private final FilteredLogger logger;
165
    private final VCSGisCodeGenerator codeGenerator;
166
    private final ChangeListenerHelper workspaceEntitiesChangeListeners;
167
    private final ChangeListenerHelper repositoryEntitiesChangeListeners;
168

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

    
191
    @SuppressWarnings("LeakingThisInConstructor")
192
    public VCSGisWorkspaceImpl(JDBCServerExplorer wsexplorer, VCSGisCodeGenerator codeGenerator) {
193
        this.logger = new FilteredLogger(LOGGER, "VCSGisWorkspace", 100);
194
        this.logger.setInterval(10000);
195
        this.codeGenerator = codeGenerator;
196
        this.storesCache = new HashMap<>();
197
        this.wsexplorer = wsexplorer;
198
        this.workspaceEntitiesChangeListeners = ToolsSwingLocator.getToolsSwingManager().createChangeListenerHelper();
199
        this.repositoryEntitiesChangeListeners = ToolsSwingLocator.getToolsSwingManager().createChangeListenerHelper();
200
        this.userIdentificationRequester = null;
201

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

    
218
    private String getProviderName() {
219
        return this.wsexplorer.getProviderName();
220
    }
221

    
222
    public void initialize() throws Exception {
223
        DataManager dataManager = DALLocator.getDataManager();
224

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

    
247
    private String getMessageLabel() {
248
        return this.wsexplorer.getParameters().getUrl();
249
    }
250

    
251
    @Override
252
    public String getCode() {
253
        return this.code;
254
    }
255

    
256
    @Override
257
    public String getLabel() {
258
        return this.label;
259
    }
260

    
261
    @Override
262
    public void dispose() {
263
        for (Map.Entry<String, FeatureStore> entry : storesCache.entrySet()) {
264
            FeatureStore store = entry.getValue();
265
            if (store != null) {
266
                DisposeUtils.disposeQuietly(store);
267
            }
268
        }
269
        this.storesCache.clear();
270
        DisposeUtils.dispose(this.wsexplorer);
271
        this.wsexplorer = null;
272
        this.code = null;
273
    }
274

    
275
    @Override
276
    public JDBCServerExplorerParameters getExplorerParameters() {
277
        return this.wsexplorer.getParameters();
278
    }
279

    
280
    private boolean isInStoreIgnoreChanges(FeatureStore store) {
281
        if (this.storeIgnoreChanges == null) {
282
            return false;
283
        }
284
        return this.storeIgnoreChanges.contains(store);
285
    }
286

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

    
294
    private void removeStoreIgnoreChanges(FeatureStore store) {
295
        if (this.storeIgnoreChanges == null) {
296
            this.storeIgnoreChanges = new HashSet<>();
297
        }
298
        this.storeIgnoreChanges.remove(store);
299
    }
300

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

    
352
        } catch (Exception ex) {
353
            throw new VCSGisRuntimeException(ERR_CANT_RETRIEVE_ENTITIES, VCSGisUtils.getErrorMessage(ERR_CANT_RETRIEVE_ENTITIES));
354
        } finally {
355
            DisposeUtils.disposeQuietly(store);
356
        }
357
    }
358

    
359
    public ChangeListenerSupport getWorkspaceEntiesChangeListeners() {
360
        return this.workspaceEntitiesChangeListeners;
361
    }
362

    
363
    public ChangeListenerSupport getRepositoryEntiesChangeListeners() {
364
        return this.repositoryEntitiesChangeListeners;
365
    }
366

    
367
    @Override
368
    public List<VCSGisWorkspaceEntity> getWorkspaceEntities() {
369
        List<VCSGisWorkspaceEntity> entities = new ArrayList<>();
370
        entities.addAll(this.getEntitiesAsEntityRow());
371
        return entities;
372
    }
373

    
374
    private Collection<EntityRow> getEntitiesAsEntityRow() {
375
        if (this.workspaceEntitiesByName == null) {
376
            reloadWorkspaceEntities();
377
        }
378
        return this.workspaceEntitiesByName.values();
379
    }
380

    
381
    @Override
382
    public EntityRow getWorkspaceEntityByName(String name) {
383
        if (this.workspaceEntitiesByName == null) {
384
            this.reloadWorkspaceEntities();
385
        }
386
        return this.workspaceEntitiesByName.get(name);
387
    }
388

    
389
    @Override
390
    public EntityRow getWorkspaceEntityByCode(String code) {
391
        if (this.workspaceEntitiesByCode == null) {
392
            this.reloadWorkspaceEntities();
393
        }
394
        return this.workspaceEntitiesByCode.get(code);
395
    }
396

    
397
    @Override
398
    public boolean existsInWorkspace(String entity) {
399
        EntityRow lentity = this.getWorkspaceEntity(entity);
400
        return lentity!=null;
401
    }
402

    
403
    @Override
404
    public boolean existsInWorkspace(VCSGisEntity entity) {
405
        if( entity==null ) {
406
            return false;
407
        }
408
        return this.existsInWorkspace(entity.getEntityCode());
409
    }
410
    
411
    @Override
412
    public EntityRow getWorkspaceEntity(String entity) {
413
        EntityRow wsentity = this.getWorkspaceEntityByCode(entity);
414
        if (wsentity == null) {
415
            wsentity = this.getWorkspaceEntityByName(entity);
416
        }
417
        return wsentity;
418
    }
419

    
420
    @Override
421
    public VCSGisEntity getRepositoryEntityByCode(String entityCode) {
422
        if (this.repositoryEntitiesByCode == null) {
423
            reloadRepositoryEntities(null);
424
        }
425
        return this.repositoryEntitiesByCode.get(entityCode);
426
    }
427

    
428
    @Override
429
    public VCSGisEntity getRepositoryEntityByName(String entityName) {
430
        if (this.repositoryEntitiesByCode == null) {
431
            reloadRepositoryEntities(null);
432
        }
433
        for (VCSGisEntity entity : this.repositoryEntitiesByCode.values()) {
434
            if (StringUtils.equalsIgnoreCase(entity.getEntityName(), entityName)) {
435
                return entity;
436
            }
437
        }
438
        return null;
439
    }
440

    
441
    @Override
442
    public VCSGisEntity getEntity(String entityName) {
443
        VCSGisEntity entity = this.getWorkspaceEntity(entityName);
444
        if (entity == null) {
445
            entity = this.getRepositoryEntity(entityName);
446
        }
447
        return entity;
448
    }
449

    
450
    @Override
451
    public VCSGisEntity getRepositoryEntity(String entity) {
452
        VCSGisEntity rentity = this.getRepositoryEntityByCode(entity);
453
        if (rentity == null) {
454
            rentity = this.getRepositoryEntityByName(entity);
455
        }
456
        return rentity;
457
    }
458

    
459
    @Override
460
    public void forceReloadWorkspaceEntities() {
461
        this.workspaceEntitiesByCode = null;
462
        this.workspaceEntitiesByName = null;
463
    }
464

    
465
    @Override
466
    public void create_table(String name) {
467
        EntityRow entity = this.getWorkspaceEntityByName(name);
468
        if (entity == null) {
469
            throw new IllegalArgumentException("Can't locate informacion of table '" + name + "'.");
470
        }
471
        create_table(entity);
472
    }
473

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

    
489
        } catch (Exception ex) {
490
            throw new RuntimeException("Can't create table '" + entity.getEntityName() + "'.", ex);
491
        }
492

    
493
    }
494

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

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

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

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

    
600
    @Override
601
    public FeatureStore openFeatureStore(String tableName) {
602
        DataManager dataManager = DALLocator.getDataManager();
603
        try {
604
            JDBCStoreParameters params = this.wsexplorer.get(tableName);
605
            FeatureStore store = (FeatureStore) dataManager.openStore(
606
                    getProviderName(),
607
                    params
608
            );
609

    
610
            return store;
611
        } catch (Exception ex) {
612
            LOGGER.trace("can't open store from '" + this.getMessageLabel() + "'.", ex);
613
            return null;
614
        }
615
    }
616

    
617
    @Override
618
    public String createUniqueCode() {
619
        return this.codeGenerator.generateCode();
620
    }
621

    
622
    @Override
623
    public String getErrorMessage(int errcode) {
624
        return VCSGisUtils.getErrorMessage(errcode);
625
    }
626

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

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

    
681
                }
682

    
683
                return ERR_OK;
684
            }
685

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

    
705
            change.insert(changesStore);
706
            return ERR_OK;
707
        } catch (Exception ex) {
708
            LOGGER.warn("Can't add change (op " + VCSGisUtils.getOperationLabel(operation) + ", " + entity.getEntityName() + ")", ex);
709
            return ERR_CANT_ADD_CHANGE;
710
        }
711
    }
712

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

    
735
                    case OP_DELETE:
736
                        return ERR_CANT_ADD_CHANGE;
737
                }
738
            }
739

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

    
759
    @Override
760
    public int addEntity(FeatureType featureType, String name, String description, String fieldForLabel) {
761
        return this.addEntity(featureType, name, description, fieldForLabel, null, null, null);
762
    }
763

    
764
    @Override
765
    public int addEntity(FeatureType featureType, String name, String description, String fieldForLabel, String category, String label, String pkName) {
766
        FeatureStore store = null;
767
        int err = ERR_NO_ERROR;
768
        try {
769
            LOGGER.debug("===: ADD_ENTITY " + this.getCode() + ", '" + this.getLabel() + "', " + name);
770
            EditableFeatureType ft = featureType.getCopy().getEditable();
771

    
772
            for (FeatureAttributeDescriptor attr : ft.getPrimaryKey()) {
773
                EditableFeatureAttributeDescriptor editAttr = (EditableFeatureAttributeDescriptor) attr;
774
                editAttr.setIsPrimaryKey(false);
775
                editAttr.setAllowNull(false);
776
                editAttr.setIsIndexed(true);
777
                editAttr.setAllowIndexDuplicateds(false);
778
            }
779

    
780
            EditableFeatureAttributeDescriptor attr = (EditableFeatureAttributeDescriptor) ft.getAttributeDescriptor(FEATURECODE_FIELD_NAME);
781
            if (attr == null) {
782
                err = ERR_ENTITY_NOT_HAS_VCSGISCODE;
783
                ft.add(FEATURECODE_FIELD_NAME, DataTypes.STRING)
784
                        .setSize(40)
785
                        .setIsPrimaryKey(true)
786
                        .setIsIndexed(true)
787
                        .setAllowIndexDuplicateds(false)
788
                        .setLabel("VCSGIS Code");
789
                ft.setHasOID(false);
790
            } else {
791
                if (!attr.isPrimaryKey()) {
792
                    attr.setIsPrimaryKey(true);
793
                    ft.setHasOID(false);
794
                }
795
            }
796

    
797
            EditableFeatureAttributeDescriptor geomattr = (EditableFeatureAttributeDescriptor) ft.getDefaultGeometryAttribute();
798
            if( geomattr!=null ) {
799
                geomattr.setIsIndexed(true);
800
            }
801

    
802
            featureType = ft.getNotEditableCopy();
803
            if (featureType.getAttributeDescriptor(fieldForLabel) == null) {
804
                FeatureAttributeDescriptor[] pk = featureType.getPrimaryKey();
805
                if (pk == null || pk.length < 1) {
806
                    fieldForLabel = featureType.getAttributeName(0);
807
                } else {
808
                    fieldForLabel = pk[0].getName();
809
                }
810
            }
811

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

    
829
            this.forceReloadWorkspaceEntities();
830
            err = ERR_CANT_INSERT_CHANGE;
831

    
832
            entity = this.getWorkspaceEntityByName(name);
833
            FeatureStore changesStore = this.getFeatureStore(WorkspaceChangesTable.TABLE_NAME);
834
//            addChange(entity, OP_ADD_ENTITY, changesStore, null, null);
835

    
836
            WorkspaceChangeRow change = new WorkspaceChangeRow(this);
837
            change.newCode();
838
            change.setEntityCode(entity.getCode());
839
            change.setFeatureCode(null);
840
            change.setOperation(OP_ADD_ENTITY);
841
            change.setSelected(true);
842
            change.insert();
843

    
844
            this.create_table(entity);
845

    
846
        } catch (VCSGisRuntimeException ex) {
847
            LOGGER.warn("can't add entity '" + name + "'.", ex);
848
            if (store != null) {
849
                store.cancelEditingQuietly();
850
            }
851
            return ex.getErrnum();
852
        } catch (Exception ex) {
853
            LOGGER.warn("can't add entity '" + name + "'.", ex);
854
            if (store != null) {
855
                store.cancelEditingQuietly();
856
            }
857
            return err;
858
        } finally {
859
            DisposeUtils.disposeQuietly(store);
860
        }
861
        return ERR_NO_ERROR;
862
    }
863

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

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

    
985
    @Override
986
    public int add(String name, FeatureStore source, String fieldForLabel, String category, String label) {
987
        return this.add(name, source, fieldForLabel, category, label, null, null);
988
    }
989

    
990
    @Override
991
    public int add(String name, FeatureStore source, String fieldForLabel, String category, String label, String pkName, SimpleTaskStatus status) {
992
        if (isInMyDatabase(source)) {
993
            return addExistingTable(name, source, fieldForLabel, category, label, pkName, status);
994
        } else {
995
            return addNewTable(name, source, fieldForLabel, category, label, pkName, status);
996
        }
997

    
998
    }
999

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

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

    
1040
            FeatureStore changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
1041
            transaction.add(changesStore);
1042
            changesStore.edit(MODE_APPEND);
1043

    
1044
            this.addStoreIgnoreChanges(target);
1045
            entity = this.getWorkspaceEntityByName(name);
1046

    
1047
            status.message(null);
1048
            status.setRangeOfValues(0, srcFeatures.size64());
1049
            status.setCurValue(0);
1050
            for (Feature srcFeature : srcFeatures) {
1051
                EditableFeature targetFeature;
1052
                String featureCode = this.createUniqueCode();
1053
                targetFeature = target.createNewFeature(srcFeature);
1054
                targetFeature.set(FEATURECODE_FIELD_NAME, featureCode);
1055
                target.insert(targetFeature);
1056

    
1057
                WorkspaceChangeRow change = new WorkspaceChangeRow(this);
1058
                change.newCode();
1059
                change.setEntityCode(entity.getEntityCode());
1060
                change.setFeatureCode(featureCode);
1061
                change.setOperation(OP_INSERT);
1062
                change.setLabel(targetFeature.getString(entity.getFieldForLabel()));
1063
                change.setSelected(true);
1064
                change.setStatus(STATE_LOCAL_NEW);
1065
                change.insert(changesStore);
1066

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

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

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

    
1117
            FeatureType featureType = source.getDefaultFeatureType();
1118
            FeatureAttributeDescriptor attr = featureType.getAttributeDescriptor(FEATURECODE_FIELD_NAME);
1119
            if (attr == null) {
1120
//                explorer.execute("ALTER TABLE \""+name+"\" ADD COLUMN \""+FEATURECODE_FIELD_NAME+"\" VARCHAR(40)");
1121
                explorer.execute(
1122
                        String.format(
1123
                                VCSGisUtils.getSqlTemplate(explorer.getProviderName(), "alterTableAddColumnVCSGISCODE"),
1124
                                name
1125
                        )
1126
                );
1127
            }
1128

    
1129
            ResourcesStorage resourcesStorage = source.getResourcesStorage();
1130
            if (resourcesStorage != null) {
1131
                Resource resource = resourcesStorage.getResource("dal");
1132
                if (resource != null) {
1133
                    resourcesStorage.remove(resource.getName());
1134
                }
1135
            }
1136

    
1137
            target = (FeatureStore) dataManager.openStore(source.getProviderName(), source.getParameters());
1138

    
1139
            transaction.add(target);
1140
            errcode = ERR_CANT_RETRIEVE_SOURCE_FEATURES;
1141
            status.message(i18n.getTranslation("_Preparing_source"));
1142
            targetFeatures = target.getFeatureSet();
1143
            transaction.add(targetFeatures);
1144
            errcode = ERR_CANT_INSERT_FEATURES;
1145
            target.edit(MODE_PASS_THROUGH);
1146

    
1147
            FeatureStore changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
1148
            transaction.add(changesStore);
1149
            changesStore.edit(MODE_APPEND);
1150

    
1151
            FeatureStore entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1152
            transaction.add(entitiesStore);
1153
            entitiesStore.edit(MODE_FULLEDIT);
1154

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

    
1175
            this.forceReloadWorkspaceEntities();
1176
            errcode = ERR_CANT_INSERT_CHANGE;
1177

    
1178
            entity = this.getWorkspaceEntityByName(name);
1179

    
1180
//            addChange(entity, OP_ADD_ENTITY, changesStore, null, null);
1181
            WorkspaceChangeRow change = new WorkspaceChangeRow(this);
1182
            change.newCode();
1183
            change.setEntityCode(entity.getCode());
1184
            change.setFeatureCode(null);
1185
            change.setOperation(OP_ADD_ENTITY);
1186
            change.setSelected(true);
1187
            change.insert(changesStore);
1188

    
1189
            status.message(null);
1190
            status.setRangeOfValues(0, targetFeatures.size64());
1191
            status.setCurValue(0);
1192
            for (Feature targetFeature : targetFeatures) {
1193
                EditableFeature editableFeature;
1194
                String featureCode = this.createUniqueCode();
1195

    
1196
                editableFeature = targetFeature.getEditable();
1197
                editableFeature.set(FEATURECODE_FIELD_NAME, featureCode);
1198
                targetFeatures.update(editableFeature);
1199

    
1200
                change = new WorkspaceChangeRow(this);
1201
                change.newCode();
1202
                change.setEntityCode(entity.getEntityCode());
1203
                change.setFeatureCode(featureCode);
1204
                change.setOperation(OP_INSERT);
1205
                change.setLabel(editableFeature.getString(entity.getFieldForLabel()));
1206
                change.setSelected(true);
1207
                change.setStatus(STATE_LOCAL_NEW);
1208
                change.insert(changesStore);
1209

    
1210
                status.incrementCurrentValue();
1211
                if (status.isCancellationRequested()) {
1212
                    transaction.rollbackQuietly();
1213
                    status.cancel();
1214
                    return ERR_CANCELLED_BY_USER;
1215
                }
1216
            }
1217

    
1218
            target.finishEditing();
1219

    
1220
//            explorer.execute("ALTER TABLE \""+name+"\" DROP PRIMARY KEY");
1221
            explorer.execute(
1222
                    String.format(
1223
                            VCSGisUtils.getSqlTemplate(explorer.getProviderName(), "alterTableDropPrimaryKey"),
1224
                            entity.getEntityName()
1225
                    )
1226
            );
1227

    
1228
//            explorer.execute("ALTER TABLE \""+name+"\" ALTER COLUMN \""+FEATURECODE_FIELD_NAME+"\" SET NOT NULL");
1229
            explorer.execute(
1230
                    String.format(
1231
                            VCSGisUtils.getSqlTemplate(explorer.getProviderName(), "alterTableAlterColumnVCSGISCODESetNotNull"),
1232
                            entity.getEntityName()
1233
                    )
1234
            );
1235

    
1236
//            explorer.execute("ALTER TABLE \""+name+"\" ADD PRIMARY KEY (\""+FEATURECODE_FIELD_NAME+"\")");
1237
            explorer.execute(
1238
                    String.format(
1239
                            VCSGisUtils.getSqlTemplate(explorer.getProviderName(), "alterTableAddPrimaryKeyVCSGISCODE"),
1240
                            entity.getEntityName()
1241
                    )
1242
            );
1243

    
1244
            target = (FeatureStore) dataManager.openStore(source.getProviderName(), source.getParameters());
1245

    
1246
            EditableFeatureType ft = target.getDefaultFeatureTypeQuietly().getEditable();
1247
            EditableFeatureAttributeDescriptor geomattr = (EditableFeatureAttributeDescriptor) ft.getDefaultGeometryAttribute();
1248
            if( geomattr!=null ) {
1249
                geomattr.setIsIndexed(true);
1250
            }
1251

    
1252
            entitiesStore.edit(MODE_FULLEDIT);
1253

    
1254
            entity.setFeatureTypeAsJson(ft.toJsonBuilder().toString());
1255
            entity.update(entitiesStore);
1256

    
1257
            entitiesStore.finishEditing();
1258

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

    
1273
    @Override
1274
    public VCSGisWorkspaceChanges<VCSGisWorkspaceChange> getLocalChanges() {
1275
        return getLocalChanges(null);
1276
    }
1277

    
1278
    @Override
1279
    public VCSGisWorkspaceChanges<VCSGisWorkspaceChange> getLocalChanges(List<VCSGisEntity> entities) {
1280
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1281
        ChangesImpl changes = new ChangesImpl<WorkspaceChangeRow>(changesTable.getByEntityCode(this, entities), WorkspaceChangesTable.SELECTED) {
1282
            @Override
1283
            protected WorkspaceChangeRow createChange(Feature f) {
1284
                return new WorkspaceChangeRow(VCSGisWorkspaceImpl.this, f);
1285
            }
1286

    
1287
            @Override
1288
            protected void updateChange(FeatureStore store, WorkspaceChangeRow change) {
1289
                change.update(store);
1290
            }
1291

    
1292
        };
1293
        return changes;
1294
    }
1295

    
1296
//    @Override
1297
//    public VCSGisWorkspaceChanges<VCSGisWorkspaceChange> getLocalChangesByEntityCodeOrName(String codeOrName) {
1298
//        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1299
//        ChangesImpl changes = new ChangesImpl<WorkspaceChangeRow>(changesTable.getByEntityCode(this, codeOrName), WorkspaceChangesTable.SELECTED) {
1300
//            @Override
1301
//            protected WorkspaceChangeRow createChange(Feature f) {
1302
//                return new WorkspaceChangeRow(VCSGisWorkspaceImpl.this, f);
1303
//            }
1304
//
1305
//            @Override
1306
//            protected void updateChange(FeatureStore store, WorkspaceChangeRow change) {
1307
//                change.update(store);
1308
//            }
1309
//
1310
//        };
1311
//        return changes;
1312
//    }
1313

    
1314
//    @Override
1315
//    public VCSGisWorkspaceChanges<VCSGisWorkspaceChange> getLocalChangesByEntityName(String entityName) {
1316
//        EntityRow entity = this.getWorkspaceEntityByName(entityName);
1317
//        return getLocalChangesByEntityCode(entity.getEntityCode());
1318
//    }
1319
//
1320
//    @Override
1321
//    public VCSGisWorkspaceChanges<VCSGisWorkspaceChange> getLocalChangesByEntityCode(String entityCode) {
1322
//        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1323
//        ChangesImpl changes = new ChangesImpl<WorkspaceChangeRow>(changesTable.getByEntityCode(this,entityCode),WorkspaceChangesTable.SELECTED) {
1324
//            @Override
1325
//            protected WorkspaceChangeRow createChange(Feature targetFeature) {
1326
//                return new WorkspaceChangeRow(VCSGisWorkspaceImpl.this, targetFeature);
1327
//            }
1328
//
1329
//            @Override
1330
//            protected void updateChange(FeatureStore store, WorkspaceChangeRow change) {
1331
//                change.update(store);
1332
//            }
1333
//
1334
//        };
1335
//        return changes;
1336
//    }
1337
    @Override
1338
    public VCSGisRepository getRepository() {
1339
        return repository;
1340
    }
1341

    
1342
    @Override
1343
    public List<VCSGisEntity> getEntitiesOfRemoteChanges() {
1344
        ArrayList<VCSGisEntity> res = new ArrayList<>();
1345
        RemoteChangesTable changesTable = new RemoteChangesTable();
1346
        DisposableFeatureSetIterable features = changesTable.getGroupedByEntity(this);
1347
        EntitiesRepoTable entitiesRepoTable = new EntitiesRepoTable();
1348
        for (Feature feature : features) {
1349
            VCSGisEntity entity = entitiesRepoTable.getByEntityCode((VCSGisRepositoryLocaldb) this.getRepository(), feature.getString(RemoteChangesTable.COD_ENTITY));
1350
            res.add(entity);
1351
        }
1352
        DisposeUtils.disposeQuietly(features);
1353
        return res;
1354
    }
1355

    
1356
    @Override
1357
    public VCSGisWorkspaceChanges<VCSGisRepositoryChange> getRemoteChanges() {
1358
        return getRemoteChangesByEntity(null);
1359
    }
1360

    
1361
    @Override
1362
    public VCSGisWorkspaceChanges<VCSGisRepositoryChange> getRemoteChangesByEntity(String entityName) {
1363
        String entityCode;
1364
        if (StringUtils.isBlank(entityName)) {
1365
            entityCode = null;
1366
        } else {
1367
            VCSGisEntity entity = this.getWorkspaceEntity(entityName);
1368
            if (entity == null) {
1369
                entity = this.getRepositoryEntity(entityName);
1370
                if (entity == null) {
1371
                    return null;
1372
                }
1373
            }
1374
            entityCode = entity.getEntityCode();
1375
        }
1376
        RemoteChangesTable changesTable = new RemoteChangesTable();
1377
        ChangesImpl changes = new ChangesImpl<RemoteChangeRow>(changesTable.getByEntityCode(this, entityCode), RemoteChangesTable.SELECTED) {
1378
            @Override
1379
            protected RemoteChangeRow createChange(Feature f) {
1380
                return new RemoteChangeRow(VCSGisWorkspaceImpl.this, f);
1381
            }
1382

    
1383
            @Override
1384
            protected void updateChange(FeatureStore store, RemoteChangeRow change) {
1385
                change.update(store);
1386
            }
1387

    
1388
        };
1389
        return changes;
1390
    }
1391

    
1392
    private Timestamp now() {
1393
        return Timestamp.from(LocalDateTime.now().toInstant(ZoneOffset.UTC));
1394
    }
1395

    
1396
    public List<VCSGisEntity> getEntitiesOfLocalChanges() {
1397
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1398
        List<VCSGisEntity> entities = new ArrayList<>();
1399

    
1400
        DisposableFeatureSetIterable changesGroupedByEntity = changesTable.getGroupedByEntity(this);
1401
        
1402
        for (Feature fchange : changesGroupedByEntity) {
1403
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1404
            VCSGisEntity localEntity = change.getEntity();
1405
            if (change.isSelected()) {
1406
                entities.add(localEntity);
1407
            }
1408
        }
1409
        return entities;  
1410
    }
1411
    
1412
    @SuppressWarnings("Convert2Lambda")
1413
    public boolean prepareCommitRequest(VCSGisCommitRequest request, List<String> entityCodes, Timestamp revisiondate, Timestamp efectivedate, String comment, SimpleTaskStatus status) {
1414
        boolean isMyStatus = false;
1415
        if (status == null) {
1416
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Prepare commit request");
1417
            status.setAutoremove(true);
1418
            status.add();
1419
            isMyStatus = true;
1420
        }
1421
        request.setEfectiveDate(efectivedate);
1422
        request.setRevisionDate(revisiondate);
1423
        request.setComment(comment);
1424
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1425

    
1426
        LOGGER.debug("===: COMMIT: Adding changed local entities");
1427
        status.message("Searching changed entities");
1428
        // adicionamos las entidades que vamos a actualizar con las revisiones que tenemos.
1429
        DisposableFeatureSetIterable changesGroupedByEntity = changesTable.getGroupedByEntity(this);
1430
//        status.setRangeOfValues(0, changesGroupedByEntity.size64());
1431
        status.setCurValue(0);
1432
        for (Feature fchange : changesGroupedByEntity) {
1433
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1434
            VCSGisWorkspaceEntity localEntity = change.getEntity();
1435
            LOGGER.debug("===: COMMIT: add used entity = " + fchange.toJson().toString().replace('\n', ' '));
1436
            if (change.isSelected()) {
1437
                if(CollectionUtils.isEmpty(entityCodes) || entityCodes.contains(localEntity.getEntityCode())){
1438
                    request.add(request.createEntity(localEntity));
1439
                }
1440
            }
1441
            status.incrementCurrentValue();
1442
        }
1443
        changesGroupedByEntity.dispose();
1444

    
1445
        LOGGER.debug("===: COMMIT: Mark new local entities");
1446
        status.message("Searching new entities");
1447
        // Marcamos como nuevas las entidades que se han dado de alta.
1448
        DisposableFeatureSetIterable changesOfAddEntities = changesTable.getByOperation(this, OP_ADD_ENTITY);
1449
        for (Feature fchange : changesOfAddEntities) {
1450
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1451
            if (change.isSelected()) {
1452
                if(CollectionUtils.isEmpty(entityCodes) || entityCodes.contains(change.getEntityCode())){
1453
                    request.markAsNew(change.getEntity());
1454
                }
1455
            }
1456
        }
1457
        changesOfAddEntities.dispose();
1458

    
1459
        LOGGER.debug("===: COMMIT: Adding data");
1460
        status.message("Searching changed data");
1461
        // adicionamos los datos
1462
        boolean useSeleccion = true;
1463
        DisposableFeatureSetIterable changes = changesTable.getSelectedsWithoutAddEntity(this, entityCodes);
1464
        if (changes != null) {
1465
            request.add(new DisposableIterableAdapter(
1466
                    changes,
1467
                    new DisposableIterableAdapter.ItemConverter<Feature, VCSGisChange>() {
1468
                @Override
1469
                public VCSGisChange convert(Feature f) {
1470
                    return new WorkspaceChangeRow(VCSGisWorkspaceImpl.this, f);
1471
                }
1472
            }
1473
            )
1474
            );
1475
        }
1476
        if (isMyStatus) {
1477
            status.terminate();
1478
        }
1479
        return useSeleccion;
1480
    }
1481

    
1482
    @Override
1483
    public boolean canCommit() {
1484
        return canCommit(null);
1485
    }
1486

    
1487
    @Override
1488
    public boolean canCommit(MutableObject<String> message) {
1489
        return canCommit(message, null);
1490
    }
1491

    
1492
    @Override
1493
    public boolean canCommit(MutableObject<String> message, List<String> entityCodes) {
1494

    
1495
        List<String> outdatedEntityNames = new ArrayList<>();
1496
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1497
        DisposableFeatureSetIterable changesGroupedByEntity = null;
1498
        try {
1499

    
1500
            changesGroupedByEntity = changesTable.getGroupedByEntity(this);
1501
            for (Feature fchange : changesGroupedByEntity) {
1502
                WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1503
                VCSGisWorkspaceEntity entity = change.getEntity();
1504
                if(CollectionUtils.isEmpty(entityCodes) || entityCodes.contains(entity.getEntityCode())){
1505
                    LOGGER.debug("===: CAN-COMMIT: add used entity = " + fchange.toJson().toString().replace('\n', ' '));
1506
                    if (change.isSelected() && entity.isOutdated()) {
1507
                        outdatedEntityNames.add(entity.getEntityName());
1508
                    }
1509
                }
1510
            }
1511
            DisposeUtils.dispose(changesGroupedByEntity);
1512

    
1513
            if (!outdatedEntityNames.isEmpty()) {
1514
                if (message != null) {
1515
                    I18nManager i18n = ToolsLocator.getI18nManager();
1516
                    String msg = i18n.getTranslation("_Tables_in_working_copy_are_outdated")
1517
                            + ". ("
1518
                            + StringUtils.join(outdatedEntityNames, ", ")
1519
                            + ")";
1520
                    message.setValue(msg);
1521
                }
1522
                return false;
1523
            }
1524
            return true;
1525
        } catch (Exception ex) {
1526
            return false;
1527
        } finally {
1528
            DisposeUtils.dispose(changesGroupedByEntity);
1529
        }
1530
    }
1531

    
1532
    @Override
1533
    public List<VCSGisWorkspaceEntity> getEntitiesWithChanges() {
1534

    
1535
        List<VCSGisWorkspaceEntity> entities = new ArrayList<>();
1536
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1537
        DisposableFeatureSetIterable changesGroupedByEntity = null;
1538
        try {
1539

    
1540
            changesGroupedByEntity = changesTable.getGroupedByEntity(this);
1541
            for (Feature fchange : changesGroupedByEntity) {
1542
                WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1543
                VCSGisWorkspaceEntity entity = change.getEntity();
1544
                if (change.isSelected()) {
1545
                    entities.add(entity);
1546
                }
1547
            }
1548
            return entities;
1549

    
1550
        } catch (Exception ex) {
1551
            return null;
1552
        } finally {
1553
            DisposeUtils.dispose(changesGroupedByEntity);
1554
        }
1555
    }
1556

    
1557
    @Override
1558
    public int commit() {
1559
        return commit(null, null, now(), null, null);
1560
    }
1561

    
1562
    @Override
1563
    public int commit(Timestamp efectivedate, String comment, SimpleTaskStatus status) {
1564
        return commit(null, null, efectivedate, comment, status);
1565
    }
1566

    
1567
    @Override
1568
    public int commit(Timestamp revisiondate, Timestamp efectivedate, String comment, SimpleTaskStatus status) {
1569
        return commit(null, revisiondate, efectivedate, comment, status);
1570
    }
1571

    
1572
    @Override
1573
    @SuppressWarnings("Convert2Lambda")
1574
    public int commit(List<String> entityCodes, Timestamp revisiondate, Timestamp efectivedate, String comment, SimpleTaskStatus status) {
1575
        VCSGisCommitRequest request = null;
1576
        if (status == null) {
1577
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Commit");
1578
            status.setAutoremove(true);
1579
            status.add();
1580
        }
1581
        try {
1582
            LOGGER.debug("===: COMMIT " + this.getCode() + ", " + this.getLabel());
1583
            EntitiesTable entitiesTable = new EntitiesTable();
1584
            WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1585

    
1586
            status.message("Preparing commit");
1587
            reloadRepositoryEntities(status);
1588
            request = this.getRepository().createCommitRequest();
1589
            request.setAuthenticationToken(this.authenticationToken);
1590
            request.setUserCode(this.currentUser);
1591

    
1592
            boolean useSeleccion = this.prepareCommitRequest(request, entityCodes, revisiondate, efectivedate, comment, status);
1593

    
1594
            LOGGER.debug("===: COMMIT: Do execute request");
1595
            status.message("Executing commit request");
1596
            if ( execute(request) != ERR_OK) {
1597
                status.message("Can't commit changes (error " + request.getLastErrorCode() + ")");
1598
                status.abort();
1599
                return request.getLastErrorCode();
1600
            }
1601

    
1602
            LOGGER.debug("===: COMMIT: update local entities table");
1603
            status.message("Updating local metadata");
1604
            FeatureStore entitiesStore = null;
1605
            try {
1606
                entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1607
                entitiesStore.edit(FeatureStore.MODE_FULLEDIT);
1608
                List<VCSGisWorkspaceEntity> changedLocalentities = request.getChangedLocalEntities();
1609
                status.setRangeOfValues(0, changedLocalentities.size());
1610
                status.setCurValue(0);
1611
                for (VCSGisEntity rentity : changedLocalentities) {
1612
                    EntityRow entityRow = entitiesTable.getByEntityName(this, rentity.getEntityName());
1613
                    if (entityRow != null) {
1614
                        entityRow.copyfrom(rentity);
1615
                        entityRow.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
1616
                        entityRow.update(entitiesStore);
1617
                    }
1618
                    status.incrementCurrentValue();
1619
                }
1620
                entitiesStore.finishEditing();
1621
                forceReloadWorkspaceEntities();
1622
            } catch (Exception e) {
1623
                FeatureStore.cancelEditingQuietly(entitiesStore);
1624
            } finally {
1625
                DisposeUtils.disposeQuietly(entitiesStore);
1626
                entitiesStore = null;
1627
            }
1628

    
1629
            LOGGER.debug("===: COMMIT: clean local changes");
1630
            status.message("Removing local list of changes");
1631
            if (useSeleccion) {
1632
                changesTable.deleteSelecteds(this, entityCodes);
1633
            } else {
1634
                changesTable.deleteAll(this);
1635
            }
1636
            status.message("Commit completed");
1637
            status.terminate();
1638
            return ERR_NO_ERROR;
1639
        } catch (Exception ex) {
1640
            LOGGER.warn("Can't commit changes.", ex);
1641
            status.message("Can't commit changes");
1642
            status.abort();
1643
            return ERR_CANT_COMMIT;
1644
        } finally {
1645
            DisposeUtils.disposeQuietly(request);
1646
        }
1647
    }
1648
    
1649

    
1650
    @Override
1651
    public int checkout(String tableName) {
1652
        return checkout(tableName, null);
1653
    }
1654

    
1655
    @Override
1656
    public int checkout(String tableName, String revisionCode) {
1657
        return checkout(tableName, revisionCode, null);
1658
    }
1659

    
1660
    @Override
1661
    public int checkout(String tableName, String revisionCode, SimpleTaskStatus status) {
1662
        FeatureStore target = null;
1663
        FeatureStore entitiesStore = null;
1664
        int errcode = ERR_OK;
1665
        VCSGisCheckoutRequest request = null;
1666
        if (status == null) {
1667
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("_Checkout");
1668
            status.setAutoremove(true);
1669
            status.add();
1670
        }
1671
        try {
1672
            LOGGER.debug("===: CHECKOUT " + this.getCode() + ", '" + this.getLabel() + "', " + tableName);
1673
            status.message("Preparing checkout");
1674
            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
1675
            if (lentity != null) {
1676
                status.message("Table " + tableName + " already exists");
1677
                status.abort();
1678
                return ERR_ENTITY_ALREADY_EXISTS;
1679
            }
1680
            reloadRepositoryEntities(status);
1681
            request = this.getRepository().createCheckoutRequest(tableName);
1682
            request.setAuthenticationToken(this.authenticationToken);
1683
            request.setUserCode(this.currentUser);
1684
            request.setEfectiveDate((Timestamp) null);
1685
            request.setRevisionCode(revisionCode);
1686

    
1687
            status.message("Executing checkout request for " + tableName);
1688
            if ( execute(request) != ERR_OK) {
1689
                status.message("Can't checkout " + tableName + " (error " + request.getLastErrorCode() + ")");
1690
                status.abort();
1691
                return request.getLastErrorCode();
1692
            }
1693
            status.message("Updating " + tableName + " metadata");
1694
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1695
            entitiesStore.edit(FeatureStore.MODE_FULLEDIT);
1696
            VCSGisEntity rentity = request.getEntity();
1697
            lentity = new EntityRow(this);
1698
            rentity.copyto(lentity);
1699
            lentity.insert(entitiesStore);
1700
            LOGGER.debug("===: CHECKOUT " + this.getCode() + ", '" + this.getLabel() + "', " + tableName + ", rev." + rentity.getRepositoryRevisionCode());
1701

    
1702
//            this.forceReloadWorkspaceEntities();
1703
            status.message("Creating table " + tableName);
1704
            this.create_table(lentity);
1705

    
1706
            status.message("Adding features in " + tableName);
1707
            errcode = ERR_CANT_OPEN_STORE;
1708
            target = this.openFeatureStore(lentity);
1709
            this.addStoreIgnoreChanges(target);
1710
            DisposableIterable<VCSGisRepositoryData> data = request.getData();
1711
//            long sz = ContainerUtils.size64(data); // Con tablas tochas esto deja frita la app.
1712
//            status.setRangeOfValues(0, sz);
1713
            status.setCurValue(0);
1714
            errcode = ERR_CANT_INSERT_FEATURES;
1715
            target.edit(FeatureStore.MODE_APPEND);
1716
            for (VCSGisRepositoryData d : data) {
1717
                EditableFeature f = target.createNewFeature(d.getDataAsJson());
1718
                target.insert(f);
1719
                status.incrementCurrentValue();
1720
            }
1721
            target.finishEditing();
1722

    
1723
            status.message("Updating " + tableName + " metadata");
1724
            if(StringUtils.isBlank(revisionCode)){
1725
                lentity.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
1726
            } else {
1727
                lentity.setLocalRevisionCode(revisionCode);
1728
            }
1729
            lentity.update(entitiesStore);
1730
            entitiesStore.finishEditing();
1731
            this.forceReloadWorkspaceEntities();
1732
            
1733
            UsersTable usersTable = new UsersTable();
1734
            if( StringUtils.isNotBlank(request.getUsersHashCode()) ) {
1735
                if( StringUtils.equalsIgnoreCase(usersTable.getHashCode(this), request.getUsersHashCode())) {
1736
                    updateUsersFromRepository(status);
1737
                }
1738
            }
1739
            TopologyplanTable topologyPlansTable = new TopologyplanTable();
1740
            if( StringUtils.isNotBlank(request.getTopologyPlansHashCode()) ) {
1741
                if( StringUtils.equalsIgnoreCase(topologyPlansTable.getHashCode(this), request.getTopologyPlansHashCode())) {
1742
                    updateTopologyPlansFromRepository(status);
1743
                }
1744
            }
1745
            request.dispose();
1746

    
1747
            status.message("Checkout completed");
1748
            status.terminate();
1749
            return ERR_NO_ERROR;
1750
        } catch (Exception ex) {
1751
            LOGGER.warn("Can't checkout.", ex);
1752
            status.message("Can't checkout");
1753
            status.abort();
1754
            FeatureStore.cancelEditingQuietly(target);
1755
            FeatureStore.cancelEditingQuietly(entitiesStore);
1756
            return errcode;
1757
        } finally {
1758
            DisposeUtils.disposeQuietly(request);
1759
            if (target != null) {
1760
                this.removeStoreIgnoreChanges(target);
1761
            }
1762
            DisposeUtils.disposeQuietly(target);
1763
            DisposeUtils.disposeQuietly(entitiesStore);
1764

    
1765
        }
1766
    }
1767

    
1768
    private void updateUsersFromRepository(SimpleTaskStatus status) {
1769
        FeatureStore usersStore = null;
1770
        VCSGisUsersRequest request = null;
1771
        try {
1772
            request = this.getRepository().createUsersRequest();
1773
            request.setAuthenticationToken(this.authenticationToken);
1774
            request.setUserCode(this.currentUser);
1775

    
1776
            status.message("Executing users request");
1777
            if ( execute(request) != ERR_OK) {
1778
                status.message("Can't get users (error " + request.getLastErrorCode() + ")");
1779
                return;
1780
            }
1781
            status.message("Updating users information");
1782
            usersStore = this.openFeatureStore(UsersTable.TABLE_NAME);
1783
            usersStore.edit(FeatureStore.MODE_PASS_THROUGH);
1784
            usersStore.delete("TRUE");
1785
            for (VCSGisUser user : request.getUsers()) {
1786
                UsersTable.UserRow row = new UsersTable.UserRow(this);
1787
                row.copyFrom(user);
1788
                row.insert(usersStore);
1789
            }
1790
            usersStore.finishEditing();
1791
            
1792
        } catch(Exception ex) {
1793
            LOGGER.warn("Can't update users.", ex);
1794
            status.message("Can't update users");
1795
            FeatureStore.cancelEditingQuietly(usersStore);
1796
        } finally {
1797
            DisposeUtils.disposeQuietly(request);
1798
            DisposeUtils.disposeQuietly(usersStore);
1799
        }     
1800
    }
1801
    
1802
    private void updateTopologyPlansFromRepository(SimpleTaskStatus status) {
1803
        FeatureStore topologyPlanStore = null;
1804
        VCSGisTopologyPlansRequest request = null;
1805
        try {
1806
            request = this.getRepository().createTopologyPlansRequest();
1807
            request.setAuthenticationToken(this.authenticationToken);
1808
            request.setUserCode(this.currentUser);
1809

    
1810
            status.message("Executing topology plans request");
1811
            if ( execute(request) != ERR_OK) {
1812
                status.message("Can't get topology plans (error " + request.getLastErrorCode() + ")");
1813
                return;
1814
            }
1815
            status.message("Updating topology plans information");
1816
            topologyPlanStore = this.openFeatureStore(TopologyplanTable.TABLE_NAME);
1817
            topologyPlanStore.edit(FeatureStore.MODE_PASS_THROUGH);
1818
            topologyPlanStore.delete("TRUE");
1819
            for (VCSGisTopologyPlan topologyPlan : request.getTopologyPlans()) {
1820
                TopologyplanTable.TopologyPlanRow row = new TopologyplanTable.TopologyPlanRow(this);
1821
                row.copyFrom(topologyPlan);
1822
                row.insert(topologyPlanStore);
1823
            }
1824
            topologyPlanStore.finishEditing();
1825
            
1826
        } catch(Exception ex) {
1827
            LOGGER.warn("Can't update topology plans.", ex);
1828
            status.message("Can't update topology plans");
1829
            FeatureStore.cancelEditingQuietly(topologyPlanStore);
1830
        } finally {
1831
            DisposeUtils.disposeQuietly(request);
1832
            DisposeUtils.disposeQuietly(topologyPlanStore);
1833
        }     
1834
    }
1835
    
1836
    @Override
1837
    public int updateEntitiesFromRepository() {
1838
        return this.updateEntitiesFromRepository(null);
1839
    }
1840

    
1841
    @Override
1842
    public int updateEntitiesFromRepository(SimpleTaskStatus status) {
1843
        LOGGER.debug("===: UPDATE_ENTITIES " + this.getCode() + ", '" + this.getLabel() + "'");
1844
        FeatureStore entitiesStore = null;
1845
        EntitiesTable entitiesTable = new EntitiesTable();
1846
        if (status == null) {
1847
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Update metadata tables");
1848
            status.setAutoremove(true);
1849
            status.add();
1850
        }
1851
        try {
1852
            status.message("Preparing update metadata tables");
1853
            this.reloadRepositoryEntities(status);
1854

    
1855
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1856
            entitiesStore.edit(MODE_FULLEDIT);
1857
            for (VCSGisEntity rentity : this.getRepositoryEntities()) {
1858
                EntityRow entityRow = entitiesTable.getByEntityName(this, rentity.getEntityName());
1859
                if (entityRow != null) {
1860
                    rentity.copyto(entityRow);
1861
                    entityRow.update(entitiesStore);
1862
                }
1863
            }
1864
            entitiesStore.finishEditingQuietly();
1865

    
1866
            this.reloadWorkspaceEntities();
1867
            status.message("Update metadata tables completed");
1868
            status.terminate();
1869
            return ERR_OK;
1870
        } catch (Exception ex) {
1871
            LOGGER.warn("Can't update metadata tables.", ex);
1872
            status.message("Can't update metadata tables");
1873
            status.abort();
1874
            if (entitiesStore != null) {
1875
                entitiesStore.cancelEditingQuietly();
1876
            }
1877
            return ERR_CANT_UPDATE_ENTITIES;
1878
        } finally {
1879
            DisposeUtils.disposeQuietly(entitiesStore);
1880
            entitiesStore = null;
1881
        }
1882
    }
1883

    
1884
    @Override
1885
    public int updatePrepare(String tableName) {
1886
        return updatePrepare(tableName, null);
1887
    }
1888

    
1889
    @Override
1890
    public int updatePrepare(String tableName, SimpleTaskStatus status) {
1891
        LOGGER.debug("===: UPDATE_PREPARE: " + tableName + " WS " + this.getCode() + ", '" + this.getLabel() + "'");
1892
        if (status == null) {
1893
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Update-prepare " + tableName);
1894
            status.setAutoremove(true);
1895
            status.add();
1896
        }
1897

    
1898
        FeatureStore remoteChangesStore = null;
1899
        VCSGisUpdateRequest request = null;
1900
        DisposableIterable<VCSGisRepositoryData> remoteChanges = null;
1901
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1902
        FeatureStore userStore = null;
1903
        FeatureStore localChangesStore = null;
1904
        FeatureStore entitiesStore = null;
1905
        DataTransaction transaction = null;
1906
        try {
1907
            transaction = DALLocator.getDataManager().createTransaction();
1908
            transaction.begin();
1909
            transaction.add(this.getExplorer(), false);
1910

    
1911
            status.message("Preparing update-prepare");
1912
            reloadRepositoryEntities(status);
1913
            request = this.getRepository().createUpdateRequest(tableName);
1914
            transaction.add(request);
1915
            request.setAuthenticationToken(this.authenticationToken);
1916
            request.setUserCode(this.currentUser);
1917
            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
1918
            if (lentity != null) {
1919
                request.setLocalRevisionCode(lentity.getLocalRevisionCode());
1920
            }
1921
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1922
            transaction.add(entitiesStore);
1923
            status.message("Executing update-prepare request");
1924
            if ( execute(request) != ERR_OK) {
1925
                status.message("Can't update-prepare " + tableName + " (error " + request.getLastErrorCode() + ")");
1926
                status.abort();
1927
                return request.getLastErrorCode();
1928
            }
1929
            entitiesStore.edit(MODE_FULLEDIT);
1930
            status.message("Updating " + tableName + " metadata");
1931
            LOGGER.debug("===: UPDATE_PREPARE: " + tableName + " request code " + request.getCode());
1932
            VCSGisEntity rentity = request.getEntity();
1933
            if (lentity == null) {
1934
                lentity = new EntityRow(this);
1935
                lentity.copyfrom(rentity);
1936
                lentity.setLocalRevisionCode(null);
1937
                lentity.insert(entitiesStore);
1938
            } else {
1939
                lentity.copyfrom(rentity);
1940
                lentity.update(entitiesStore);
1941
            }
1942
//            this.reloadWorkspaceEntities();
1943
            String entityCode = lentity.getCode();
1944
            LOGGER.debug("===: UPDATE_PREPARE: " + tableName + " entity code " + entityCode + ", repo rev. " + lentity.getRepositoryRevisionCode() + ", local rev. " + lentity.getLocalRevisionCode());
1945

    
1946
            status.message("Preparing remote changes container");
1947
            remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
1948
            transaction.add(remoteChangesStore);
1949
            remoteChangesStore.edit(MODE_PASS_THROUGH);
1950

    
1951
            status.message("Deleting previous temporary remote changes");
1952
            LOGGER.debug("===: UPDATE_PREPARE: Delete updates table");
1953
            remoteChangesStore.delete("\"" + COD_ENTITY + "\"='" + entityCode + "'");
1954

    
1955
            remoteChanges = request.getData();
1956
            transaction.add(remoteChanges);
1957
//            long sz = ContainerUtils.size64(remoteChanges);
1958
//            status.setRangeOfValues(0, sz);
1959
            status.setCurValue(0);
1960

    
1961
            LOGGER.debug("===: UPDATE_PREPARE: Inserting updates");
1962
            userStore = this.openFeatureStore(lentity);
1963
            localChangesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
1964
            transaction.add(userStore);
1965
            transaction.add(localChangesStore);
1966
            localChangesStore.edit(MODE_PASS_THROUGH);
1967
            status.message("Downloading list of remote changes");
1968
            for (VCSGisRepositoryData remoteChange : remoteChanges) {
1969
                RemoteChangeRow remoteChangeRow = new RemoteChangeRow(this);
1970
//                LOGGER.debug("===: UPDATE_PREPARE: insert "+remoteChange.getFeatureRelatedCode()+", "+remoteChange.getOperation()+", "+remoteChange.getData());
1971
//                remoteChangeRow.setCode(remoteChange.getFeatureRelatedCode());
1972
                remoteChangeRow.newCode();
1973
                remoteChangeRow.setData(remoteChange.getData());
1974
                remoteChangeRow.setEntityCode(remoteChange.getEntityCode());
1975
                remoteChangeRow.setDataCode(remoteChange.getFeatureRelatedCode());
1976
                remoteChangeRow.setOperation(remoteChange.getOperation());
1977
                remoteChangeRow.setRevisionCode(remoteChange.getRevisionCode());
1978
                remoteChangeRow.setRevisionNumber(remoteChange.getRevisionNumber());
1979
                switch (remoteChange.getOperation()) {
1980
                    case OP_INSERT:
1981
                        remoteChangeRow.setStatus(STATE_LOCAL_NEW);
1982
                        break;
1983
                    case OP_UPDATE:
1984
                    case OP_DELETE:
1985
                        remoteChangeRow.setStatus(STATE_LOCAL_OUTDATED);
1986
                        break;
1987
                    default:
1988
                        remoteChangeRow.setStatus(STATE_LOCAL_UNMODIFIED);
1989
                        break;
1990
                }
1991

    
1992
                if (hasConflictRemoteChangeWithUserTable(lentity, remoteChange, userStore)) {
1993
                    remoteChangeRow.setStatus(STATE_CONFLICT);
1994
                    lentity.setState(STATE_CONFLICT);
1995
                }
1996

    
1997
                LOGGER.debug("===: UPDATE_PREPARE: row code = " + remoteChangeRow.getRelatedFeatureCode());
1998
                LOGGER.debug("===: UPDATE_PREPARE: row state = " + lentity.getState() + ", " + lentity.getStateLabel());
1999
                LOGGER.debug("===: UPDATE_PREPARE: row operation = " + remoteChangeRow.getOperation() + ", " + remoteChangeRow.getOperationLabel());
2000
                switch (lentity.getState()) {
2001
                    case STATE_LOCAL_OUTDATED:
2002
                    case STATE_LOCAL_UNMODIFIED:
2003
                        remoteChangeRow.setSelected(true);
2004
                        break;
2005
                    case STATE_CONFLICT:
2006
                        remoteChangeRow.setSelected(false);
2007
                        DisposableIterable<WorkspaceChangeRow> localChanges = changesTable.getChangesWidthUserData(this, lentity, remoteChangeRow, localChangesStore);
2008
                        if (localChanges != null) {
2009
                            for (WorkspaceChangeRow localChange : localChanges) {
2010
                                localChange.setStatus(STATE_CONFLICT);
2011
                                localChange.update(localChangesStore);
2012
                            }
2013
                            localChanges.dispose();
2014
                        }
2015
                    // Don't break to continue run next cases
2016
                    case STATE_LOCAL_NEW:
2017
                    case STATE_LOCAL_OUTDATED_AND_MODIFIED:
2018
                    case STATE_LOCAL_MODIFIED:
2019
                        WorkspaceChangeRow localChange = changesTable.getByEntityAndDataCode(this,
2020
                                entityCode,
2021
                                remoteChangeRow.getRelatedFeatureCode(),
2022
                                localChangesStore
2023
                        );
2024
                        if (localChange == null) {
2025
                            LOGGER.debug("===: UPDATE_PREPARE: no local modificacion, update local data");
2026
                            // Solo actualizamos si no ha sido modificado localmente y el cambio remoto no tiene conflictos
2027
                            if (remoteChangeRow.getStatus() != STATE_CONFLICT) {
2028
                                remoteChangeRow.setSelected(true);
2029
                            }
2030
                        } else {
2031
                            LOGGER.debug("===: UPDATE_PREPARE: not update. Local data is modified. " + localChange.getRelatedFeatureData().replace('\n', ' '));
2032
                            remoteChangeRow.setSelected(false);
2033
                            if (localChange.getStatus() != STATE_CONFLICT) {
2034
                                localChange.setStatus(STATE_LOCAL_OUTDATED_AND_MODIFIED);
2035
                                localChange.update(localChangesStore);
2036
                            }
2037
                        }
2038
                        break;
2039

    
2040
                }
2041
                remoteChangeRow.insert(remoteChangesStore);
2042
                status.incrementCurrentValue();
2043
            }
2044
            LOGGER.debug("===: UPDATE_PREPARE: finish inserting updates");
2045
            lentity.update(entitiesStore);
2046

    
2047
            remoteChangesStore.finishEditing();
2048
            localChangesStore.finishEditing();
2049
            entitiesStore.finishEditing();
2050

    
2051
            updateLocallyModyfiedRemoteChanges();
2052

    
2053
            transaction.commit();
2054

    
2055
            status.message("Update-prepare completed");
2056
            status.terminate();
2057
            return ERR_OK;
2058
        } catch (Exception ex) {
2059
            LOGGER.warn("Can't prepare update.", ex);
2060
            status.message("Can't prepare update");
2061
            status.abort();
2062
            DataTransaction.rollbackQuietly(transaction);
2063
            return ERR_CANT_PREPARE_UPDATE;
2064
        } finally {
2065
            DisposeUtils.disposeQuietly(transaction);
2066
        }
2067

    
2068
    }
2069

    
2070
    private void updateLocallyModyfiedRemoteChanges() {
2071

    
2072
        RemoteChangesTable changes = new RemoteChangesTable();
2073
        changes.updateStateFromLocalChanges(this, STATE_LOCAL_OUTDATED_AND_MODIFIED);
2074

    
2075
    }
2076

    
2077
    private boolean hasConflictRemoteChangeWithUserTable(VCSGisEntity lentity, VCSGisRepositoryData remoteChange, FeatureStore store) throws DataException {
2078
        if (store != null) {
2079
            FeatureType featType = lentity.getFeatureType();
2080
            JsonObject data = remoteChange.getDataAsJson();
2081
            ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
2082
            ExpressionBuilder builder = expManager.createExpressionBuilder();
2083
            builder.set(null);
2084
            for (FeatureAttributeDescriptor attr : featType) {
2085
                if (attr.isIndexed() && !attr.allowIndexDuplicateds()) {
2086
                    Object value = Json.toObject(data, attr.getName());
2087
                    builder.and(
2088
                            builder.eq(
2089
                                    builder.column(attr.getName()),
2090
                                    builder.constant(value)
2091
                            )
2092
                    );
2093

    
2094
                    Feature f = store.findFirst(builder.toString());
2095
                    if (f != null && !StringUtils.equals(
2096
                            f.getString(lentity.getFeatureIdFieldName()),
2097
                            remoteChange.getFeatureRelatedCode())) {
2098
                        return true;
2099
                    }
2100
                }
2101
            }
2102
        }
2103
        return false;
2104
    }
2105

    
2106
//    private Feature getUserFeatureConflictWithRemoteChange(VCSGisEntity lentity, RemoteChangeRow 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
//                    Feature targetFeature = store.findFirst(builder.toString());
2123
//                    if(targetFeature != null && !StringUtils.equals(
2124
//                            targetFeature.getString(lentity.getFeatureIdFieldName()),
2125
//                            remoteChange.getRelatedFeatureCode())
2126
//                        ){
2127
//                        return targetFeature;
2128
//                    }
2129
//                }
2130
//            }
2131
//        }
2132
//        return null;
2133
//    }
2134
    private DisposableFeatureSetIterable getUserFeaturesConflictWithRemoteChange(VCSGisEntity lentity, RemoteChangeRow remoteChange, FeatureStore store) throws DataException {
2135
        if (store == null) {
2136
            return null;
2137
        }
2138
        FeatureType featType = lentity.getFeatureType();
2139
        JsonObject data = remoteChange.getRelatedFeatureDataAsJson();
2140
        ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
2141
        ExpressionBuilder builder = expManager.createExpressionBuilder();
2142
        builder.set(null);
2143
        for (FeatureAttributeDescriptor attr : featType) {
2144
            if (StringUtils.equalsAnyIgnoreCase(lentity.getFeatureIdFieldName(), attr.getName())) {
2145
                continue;
2146
            }
2147
            if (attr.isIndexed() && !attr.allowIndexDuplicateds()) {
2148
                Object value = Json.toObject(data, attr.getName());
2149
                builder.or(
2150
                        builder.eq(
2151
                                builder.column(attr.getName()),
2152
                                builder.constant(value)
2153
                        )
2154
                );
2155
            }
2156
        }
2157
        ExpressionBuilder.Value value = builder.value();
2158
        if (value == null) {
2159
            return null;
2160
        }
2161
        ExpressionBuilder.BinaryOperator filter = builder.and(
2162
                builder.not(
2163
                        builder.eq(
2164
                                builder.column(lentity.getFeatureIdFieldName()),
2165
                                builder.constant(remoteChange.getRelatedFeatureCode())
2166
                        )
2167
                ),
2168
                value
2169
        );
2170

    
2171
        FeatureSet feats = store.getFeatureSet(filter.toString());
2172
        return feats.iterable();
2173
    }
2174

    
2175
    @Override
2176
    public int updateClean(String entityCode) {
2177
        return updateClean(entityCode, null);
2178
    }
2179

    
2180
    @Override
2181
    public int updateClean(String entityCode, SimpleTaskStatus status) {
2182
        VCSGisEntity entity = this.getEntity(entityCode);
2183
        if (entity == null) {
2184
            return ERR_ENTITY_NOT_EXISTS;
2185
        }
2186
        if (status == null) {
2187
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2188
                    "Update-clean " + entity.getEntityName()
2189
            );
2190
            status.setAutoremove(true);
2191
            status.add();
2192
        }
2193
        try {
2194
            status.message("Deleting temporary remote changes (" + entity.getEntityName() + ")");
2195
            RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2196
            remoteChangesTable.delete(this, entityCode);
2197
            status.message("Delete temporary remote changes completed");
2198
            status.terminate();
2199
            return ERR_OK;
2200
        } catch (Exception ex) {
2201
            LOGGER.warn("Can't deleting temporary remote changes of " + entity.getEntityName() + ".", ex);
2202
            status.message("Can't deleting temporary remote changes of " + entity.getEntityName() + ".");
2203
            status.abort();
2204
            return ERR_CANT_UPDATE_CLEAN;
2205
        }
2206

    
2207
    }
2208

    
2209
    @Override
2210
    public int update(String tableName) {
2211
        return this.update(tableName, false, false, null);
2212
    }
2213

    
2214
    @Override
2215
    public int update(String tableName, SimpleTaskStatus status) {
2216
        return this.update(tableName, false, false, status);
2217
    }
2218

    
2219
    @Override
2220
    public int merge(String tableName) {
2221
        return this.update(tableName, false, true, null);
2222
    }
2223

    
2224
    @Override
2225
    public int merge(String tableName, SimpleTaskStatus status) {
2226
        return this.update(tableName, false, true, null, status);
2227
    }
2228
    
2229
    @Override
2230
    public int merge(String tableName, MutableLong localChangesCreated, SimpleTaskStatus status) {
2231
        return this.update(tableName, false, true, localChangesCreated, status);
2232
    }
2233

    
2234
    public int update(String tableName, boolean prepare, boolean merge, SimpleTaskStatus status) {
2235
        return update(tableName, prepare, merge, null, status);
2236
    }
2237

    
2238
    public int update(String tableName, boolean prepare, boolean merge, MutableLong localChangesCreated, SimpleTaskStatus status) {
2239
        if(localChangesCreated == null){
2240
            localChangesCreated = new MutableLong(0);
2241
        }
2242
        int errcode = ERR_NO_ERROR;
2243
        if (status == null) {
2244
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2245
                    "Update " + tableName
2246
            );
2247
            status.setAutoremove(true);
2248
            status.add();
2249
        }
2250
        if (prepare) {
2251
            errcode = this.updatePrepare(tableName, status);
2252
            if (errcode != ERR_OK) {
2253
                return errcode;
2254
            }
2255
        }
2256
        LOGGER.debug("===: UPDATE " + this.getCode() + ", '" + this.getLabel() + "', " + tableName);
2257
        RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2258
        WorkspaceChangesTable localChangesTable = new WorkspaceChangesTable();
2259

    
2260
        EditableFeature ef;
2261
        DisposableFeatureSetIterable remoteChanges = null;
2262

    
2263
        FeatureStore workspaceChangesStore = null;
2264
        FeatureStore remoteChangesStore = null;
2265
        FeatureStore userStore = null;
2266
        FeatureStore entitiesStore = null;
2267

    
2268
        DataTransaction transaction = null;
2269
        try {
2270
            transaction = DALLocator.getDataManager().createTransaction();
2271
            transaction.begin();
2272

    
2273
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
2274
            transaction.add(entitiesStore);
2275
            entitiesStore.edit(MODE_PASS_THROUGH);
2276

    
2277
            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
2278
            if (lentity == null) {
2279
                lentity = new EntityRow(this);
2280
                VCSGisEntity rentity = this.getRepositoryEntityByName(tableName);
2281
                lentity.copyfrom(rentity);
2282
                lentity.setLocalRevisionCode(null);
2283
                lentity.update(entitiesStore);
2284
            }
2285
            if (!merge) {
2286
                status.message("Checking the need to merge");
2287
                if (remoteChangesTable.updateNeedMerge(this, lentity.getEntityCode())) {
2288
                    status.message("Can't update without merge.");
2289
                    status.abort();
2290
                    return ERR_UPDATE_NEED_MERGE;
2291
                }
2292
            }
2293
            String dataCodeFieldName = lentity.getFeatureIdFieldName();
2294
            status.message("Searching remote changes (" + lentity.getEntityName() + ")");
2295

    
2296
            userStore = this.openFeatureStore(lentity);
2297
            if (userStore == null) {
2298
                this.create_table(lentity);
2299
                userStore = this.openFeatureStore(lentity);
2300
            }
2301
            transaction.add(userStore);
2302
            userStore.edit(MODE_PASS_THROUGH);
2303

    
2304
            workspaceChangesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
2305
            transaction.add(workspaceChangesStore);
2306
            workspaceChangesStore.edit(MODE_PASS_THROUGH);
2307

    
2308
            remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
2309
            transaction.add(remoteChangesStore);
2310
            remoteChangesStore.edit(MODE_PASS_THROUGH);
2311

    
2312
            remoteChanges = remoteChangesTable.getSelectedsByEntityCodeAsIterator(this, lentity.getCode());
2313
            transaction.add(remoteChanges);
2314
//            long sz = ContainerUtils.size64(remoteChanges);
2315
//            status.setRangeOfValues(0, sz);
2316
            status.setCurValue(0);
2317

    
2318
            if (!remoteChanges.isEmpty()) {
2319
                this.addStoreIgnoreChanges(userStore);
2320
                status.message("Updating table (" + lentity.getEntityName() + ")");
2321
                FeatureType type = userStore.getDefaultFeatureTypeQuietly();
2322

    
2323
                ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
2324
                ExpressionBuilder builder = expManager.createExpressionBuilder();
2325

    
2326
                for (Feature feature : remoteChanges) {
2327
                    RemoteChangeRow remoteChangeRow = new RemoteChangeRow(this, feature);
2328
                    switch (remoteChangeRow.getOperation()) {
2329
                        case OP_INSERT:
2330
                            LOGGER.debug("===: UPDATE: insert");
2331
                            switch (remoteChangeRow.getStatus()) {
2332
                                case STATE_CONFLICT:
2333
                                    DisposableFeatureSetIterable feats = getUserFeaturesConflictWithRemoteChange(lentity, remoteChangeRow, userStore);
2334
                                    if (feats != null) {
2335
                                        for (Feature feat : feats) {
2336
                                            if (feat != null) {
2337
                                                feats.getFeatureSet().delete(feat);
2338
                                                workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\" = '" + feat.getString(lentity.getFeatureIdFieldName()) + "'");
2339
                                            }
2340
                                        }
2341
                                        DisposeUtils.disposeQuietly(feats);
2342
                                    }
2343
                                //Don't break to do the default case
2344
                                default:
2345
                                    ef = userStore.createNewFeature(remoteChangeRow.getRelatedFeatureDataAsJson());
2346
                                    userStore.insert(ef);
2347
                                    break;
2348
                            }
2349
                            break;
2350
                        case OP_UPDATE:
2351
                            LOGGER.debug("===: UPDATE: update");
2352
                            JsonObject dataJson = remoteChangeRow.getRelatedFeatureDataAsJson();
2353
                            builder.set(null);
2354
                            for (FeatureAttributeDescriptor attr : type.getPrimaryKey()) {
2355
                                builder.and(
2356
                                        builder.eq(
2357
                                                builder.column(attr.getName()),
2358
                                                builder.constant(
2359
                                                        Json.toObject(dataJson.get(attr.getName()))
2360
                                                )
2361
                                        )
2362
                                );
2363
                            }
2364
                            Feature f = userStore.findFirst(builder.toString());
2365
                            if (f == null) {
2366
                                WorkspaceChangeRow localChange = localChangesTable.find(this, workspaceChangesStore, lentity.getEntityCode(), remoteChangeRow.getRelatedFeatureCode());
2367
                                if(localChange != null && localChange.getOperation() == OP_DELETE){
2368
                                    ef = userStore.createNewFeature(remoteChangeRow.getRelatedFeatureDataAsJson());
2369
                                    userStore.insert(ef);
2370
                                    break;
2371
                                } else {
2372
                                    throw new NullPointerException("Can't update null feature (" + builder.toString() + ").");
2373
                                }
2374
                            }
2375
                            ef = f.getEditable();
2376
                            ef.copyFrom(dataJson);
2377
                            userStore.update(ef);
2378
//                            workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\"='" + remoteChangeRow.getRelatedFeatureCode()+ "'");
2379
                            break;
2380

    
2381
                        case OP_DELETE:
2382
                            LOGGER.debug("===: UPDATE: delete");
2383
                            userStore.delete("\"" + dataCodeFieldName + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2384
//                            workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\"='" + remoteChangeRow.getRelatedFeatureCode()+ "'");
2385
                            break;
2386
                    }
2387
                    status.incrementCurrentValue();
2388
                }
2389
            }
2390

    
2391
            if (merge) {
2392
                status.message("Searching local changes to merge (" + lentity.getEntityName() + ")");
2393
                DisposeUtils.disposeQuietly(remoteChanges);
2394
                remoteChanges = remoteChangesTable.getNotSelectedsByEntityCodeAsIterator(this, lentity.getCode());
2395
                transaction.add(remoteChanges);
2396
//                sz = ContainerUtils.size64(remoteChanges);
2397
//                status.setRangeOfValues(0, sz);
2398
                status.setCurValue(0);
2399

    
2400
                if (!remoteChanges.isEmpty()) {
2401
                    //We edit the changesStore because we will need local changes 
2402
//                    workspaceChangesStore.edit(MODE_PASS_THROUGH);
2403

    
2404
                    //We edit the destination store because we may need to update some features (in case OP_DELETE)
2405
//                    userStore.edit(MODE_PASS_THROUGH);
2406
                    this.addStoreIgnoreChanges(userStore);
2407

    
2408
                    status.message("Adding to local changes (" + lentity.getEntityName() + ")");
2409
                    for (Feature feature : remoteChanges) {
2410
                        RemoteChangeRow remoteChangeRow = new RemoteChangeRow(this, feature);
2411
                        Feature f = userStore.findFirst("\"" + lentity.getFeatureIdFieldName() + "\" = '" + remoteChangeRow.getRelatedFeatureCode() + "'");
2412
                        switch (remoteChangeRow.getOperation()) {
2413
                            case OP_INSERT:
2414
                                LOGGER.debug("===: UPDATE: insert");
2415
                                if (f == null) {
2416
                                    this.addDeleteChange(lentity, workspaceChangesStore, remoteChangeRow.getRelatedFeatureCode(), null, null);
2417
                                } else {
2418
                                    this.addChange(lentity, OP_UPDATE, workspaceChangesStore, f, null);
2419
                                }
2420
                                localChangesCreated.increment();
2421
                                break;
2422

    
2423
                            case OP_UPDATE:
2424
                                LOGGER.debug("===: UPDATE: update");
2425
                                if (f == null) {
2426
                                    this.addDeleteChange(lentity, workspaceChangesStore, remoteChangeRow.getRelatedFeatureCode(), null, null);
2427
                                } else {
2428
                                    this.addChange(lentity, OP_UPDATE, workspaceChangesStore, f, null);
2429
                                }
2430
                                localChangesCreated.increment();
2431
                                break;
2432
                            case OP_DELETE:
2433
                                LOGGER.debug("===: UPDATE: delete");
2434
                                if (f != null) {
2435
                                    userStore.delete("\"" + dataCodeFieldName + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2436

    
2437
                                    ef = userStore.createNewFeature(f);
2438
                                    ef.setString(lentity.getFeatureIdFieldName(), this.createUniqueCode());
2439
                                    userStore.insert(ef);
2440

    
2441
                                    workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2442
                                    this.addChange(lentity, OP_INSERT, workspaceChangesStore, ef, null);
2443
                                    localChangesCreated.increment();
2444
                                }
2445
                                break;
2446
                        }
2447
                        status.incrementCurrentValue();
2448
                    }
2449
                }
2450
            }
2451
            localChangesTable.removeLocalChangesRelatedToSelectedRemoteChanges(this, lentity);
2452
            remoteChangesTable.delete(remoteChangesStore, lentity.getEntityCode());
2453

    
2454
            status.message("Updating metadata tables");
2455
            lentity.setLocalRevisionCode(lentity.getRepositoryRevisionCode());
2456
            lentity.update(entitiesStore);
2457
            forceReloadWorkspaceEntities();
2458

    
2459
            transaction.commit();
2460

    
2461
            status.message("Update completed");
2462
            status.terminate();
2463
            return ERR_OK;
2464
        } catch (Exception ex) {
2465
            LOGGER.warn("Can't update.", ex);
2466
            status.message("Can't update");
2467
            status.abort();
2468
            return ERR_CANT_UPDATE;
2469
        } finally {
2470
            this.removeStoreIgnoreChanges(userStore);
2471
            DisposeUtils.disposeQuietly(transaction);
2472
        }
2473
    }
2474

    
2475
    @Override
2476
    public JDBCServerExplorer getExplorer() {
2477
        return this.wsexplorer;
2478
    }
2479

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

    
2613
            Map<String, VCSGisEntity> tmp = new HashMap<>();
2614
            entities.forEach(entity -> {
2615
                tmp.put(entity.getEntityCode(), entity);
2616
            });
2617
            this.repositoryEntitiesByCode = tmp;
2618
            
2619
            Map<String, EntityRow> theEntitiesByName = new HashMap<>();
2620
            Map<String, EntityRow> theEntitiesByCode = new HashMap<>();
2621

    
2622
            store = openFeatureStore(EntitiesTable.TABLE_NAME);
2623
            store.edit();
2624
            fset = store.getFeatureSet();
2625
            for (Feature feature : fset.iterable()) {
2626
                EntityRow entity = new EntityRow(this, feature);
2627
                VCSGisEntity repositoryEntity = this.repositoryEntitiesByCode.get(entity.getEntityCode());
2628
                if(repositoryEntity != null && !StringUtils.equalsIgnoreCase(entity.getRepositoryRevisionCode(),repositoryEntity.getRepositoryRevisionCode())){
2629
                    entity.setRepositoryRevisionCode(repositoryEntity.getRepositoryRevisionCode());
2630
                    entity.setTopologyPlanCode(repositoryEntity.getTopologyPlanCode());
2631
                    entity.update(store, fset);
2632
                }
2633
                theEntitiesByName.put(entity.getEntityName(), entity);
2634
                theEntitiesByCode.put(entity.getCode(), entity);
2635
            }
2636
            store.finishEditing();
2637
            this.workspaceEntitiesByName = theEntitiesByName;
2638
            this.workspaceEntitiesByCode = theEntitiesByCode;
2639

    
2640
            status.message("Repository tables metadata update completed");
2641
            if (isMyStatus) {
2642
                status.terminate();
2643
            }
2644
            this.repositoryEntitiesChangeListeners.fireEvent();
2645
            this.workspaceEntitiesChangeListeners.fireEvent();
2646
        } catch (VCSGisRuntimeException ex) {
2647
            FeatureStore.cancelEditingQuietly(store);
2648
            status.message("Can't get repository tables metadata");
2649
            if (isMyStatus) {
2650
                status.abort();
2651
            }
2652
            throw ex;
2653
        } catch (Exception ex) {
2654
            FeatureStore.cancelEditingQuietly(store);
2655
            status.message("Can't get repository tables metadata");
2656
            if (isMyStatus) {
2657
                status.abort();
2658
            }
2659
            throw new VCSGisRuntimeException(ERR_CANT_RETRIEVE_ENTITIES, VCSGisUtils.getErrorMessage(ERR_CANT_RETRIEVE_ENTITIES), ex);
2660
        } finally {
2661
            DisposeUtils.disposeQuietly(fset);
2662
            DisposeUtils.disposeQuietly(store);
2663
        }
2664
    }
2665

    
2666
    private boolean hasRepositoryEntities() {
2667
        return this.repositoryEntitiesByCode != null;
2668
    }
2669
    
2670
    @Override
2671
    public List<VCSGisEntity> getRepositoryEntities() {
2672
        if (this.repositoryEntitiesByCode == null) {
2673
            reloadRepositoryEntities(null);
2674
        }
2675
        List<VCSGisEntity> entities = new ArrayList<>(this.repositoryEntitiesByCode.values());
2676
        return entities;
2677
    }
2678

    
2679
    @Override
2680
    public boolean updateNeedMerge(String entityName) {
2681
        RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2682

    
2683
        VCSGisEntity entity = this.getWorkspaceEntity(entityName);
2684
        if (entity == null) {
2685
            entity = this.getRepositoryEntity(entityName);
2686
        }
2687

    
2688
        return remoteChangesTable.updateNeedMerge(this, entity.getEntityCode());
2689
    }
2690

    
2691
    @Override
2692
    public void addToConnectionPool() {
2693
        JDBCServerExplorerParameters params = this.getExplorerParameters();
2694
        DataManager dataManager = DALLocator.getDataManager();
2695
        dataManager.getDataServerExplorerPool().add(this.getLabel(), params);
2696
    }
2697

    
2698
    @Override
2699
    public boolean isInMyDatabase(FeatureStore store) {
2700
        if (!(store.getParameters() instanceof JDBCStoreParameters)) {
2701
            return false;
2702
        }
2703
        JDBCStoreParameters storeParams = (JDBCStoreParameters) store.getParameters();
2704
        JDBCServerExplorerParameters explorerParams = this.getExplorerParameters();
2705
        if (!StringUtils.equalsIgnoreCase(storeParams.getProviderName(), explorerParams.getProviderName())) {
2706
            return false;
2707
        }
2708
        return StringUtils.equalsIgnoreCase(storeParams.getUrl(), explorerParams.getUrl());
2709
    }
2710

    
2711
    @Override
2712
    public int history(String entityName, String group, Timestamp minDate, Timestamp maxDate, int maxNumberOfRevisions, SimpleTaskStatus status) {
2713
        int errcode = ERR_OK;
2714
        if (status == null) {
2715
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2716
                    "History" + entityName
2717
            );
2718
            status.setAutoremove(true);
2719
            status.add();
2720
        }
2721
        if (maxNumberOfRevisions < 0) {
2722
            maxNumberOfRevisions = 1000;
2723
        }
2724
        if (minDate != null && maxDate != null && minDate.compareTo(maxDate) > 0) {
2725
            Timestamp x = minDate;
2726
            minDate = maxDate;
2727
            maxDate = x;
2728
        }
2729
        DataTransaction transaction = DALLocator.getDataManager().createTransaction();
2730
        try {
2731
            LOGGER.debug("===: HISTORY " + this.getCode() + ", '" + this.getLabel() + "', " + entityName);
2732
            reloadWorkspaceEntities();
2733

    
2734
            VCSGisEntity lentity = this.getEntity(entityName);
2735
            if (lentity == null) {
2736
                status.message("Can't find table '" + entityName + "'");
2737
                status.abort();
2738
                return ERR_ENTITY_NOT_EXISTS;
2739
            }
2740

    
2741
            status.message("Executing history request");
2742
            VCSGisHistoryRequest request = this.getRepository().createHistoryRequest(entityName);
2743
            transaction.add(request);
2744

    
2745
            request.setAuthenticationToken(this.authenticationToken);
2746
            request.setUserCode(this.currentUser);
2747
            request.setDateRange(minDate, maxDate);
2748
            request.setMaxNumberOfRevisions(maxNumberOfRevisions);
2749
            request.setRevisionNumberRange(-1, -1);
2750

    
2751
            if ( execute(request) != ERR_OK) {
2752
                status.message("Can't retriev history of " + entityName + " (error " + request.getLastErrorCode() + ")");
2753
                status.abort();
2754
                return request.getLastErrorCode();
2755
            }
2756
            LocalRevisionsTable localRevisionsTable = new LocalRevisionsTable();
2757
            FeatureStore localRevisionsStore = this.openFeatureStore(LocalRevisionsTable.TABLE_NAME);
2758
            transaction.add(localRevisionsStore);
2759
            localRevisionsStore.edit(MODE_PASS_THROUGH);
2760

    
2761
            status.message("Deleting previous local revision information");
2762
            localRevisionsTable.deleteByEntityCodeAndGroup(
2763
                    this,
2764
                    localRevisionsStore,
2765
                    lentity.getEntityCode(),
2766
                    group
2767
            );
2768

    
2769
            DisposableIterable<VCSGisRevision> revisions = request.getRevisions();
2770
            status.message("Adding to local revisions");
2771
//            long sz = ContainerUtils.size64(revisions);
2772
//            status.setRangeOfValues(0, sz);
2773
            status.setCurValue(0);
2774

    
2775
            long minRevision = -1;
2776
            minDate = now();
2777
            errcode = ERR_CANT_INSERT_FEATURES;
2778
            for (VCSGisRevision revision : revisions) {
2779
                LocalRevisionRow row = new LocalRevisionRow(this);
2780
                row.copyFrom(revision);
2781
                row.setGroup(group);
2782
                row.insert(localRevisionsStore);
2783
                if (minRevision < 0 || minRevision > row.getNumber()) {
2784
                    minRevision = row.getNumber();
2785
                }
2786
                if (minDate.compareTo(row.getRevisionDate()) > 0) {
2787
                    minDate = row.getRevisionDate();
2788
                }
2789
                status.incrementCurrentValue();
2790
            }
2791
            localRevisionsStore.finishEditing();
2792

    
2793
            VarsTable varsTable = new VarsTable();
2794
            varsTable.set(
2795
                    this,
2796
                    "history_" + entityName + "_" + group + "_MinDate",
2797
                    minDate.toString()
2798
            );
2799
            varsTable.set(
2800
                    this,
2801
                    "history_" + entityName + "_" + group + "_MinRevision",
2802
                    String.valueOf(minRevision)
2803
            );
2804

    
2805
            transaction.commit();
2806
            status.message("History completed");
2807
            status.terminate();
2808
            return ERR_OK;
2809
        } catch (Exception ex) {
2810
            LOGGER.warn("Can't retrieve history.", ex);
2811
            transaction.rollbackQuietly();
2812
            status.message("Can't retrieve history");
2813
            status.abort();
2814
            return errcode;
2815
        } finally {
2816
            transaction.dispose();
2817
        }
2818
    }
2819

    
2820
    @Override
2821
    public int history(String entityName, String group, int maxNumberOfRevisions, SimpleTaskStatus status) {
2822
        int errcode = ERR_OK;
2823
        if (status == null) {
2824
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2825
                    "History" + entityName
2826
            );
2827
            status.setAutoremove(true);
2828
            status.add();
2829
        }
2830
        if (maxNumberOfRevisions < 0) {
2831
            maxNumberOfRevisions = 1000;
2832
        }
2833
        DataTransaction transaction = DALLocator.getDataManager().createTransaction();
2834
        try {
2835
            LOGGER.debug("===: HISTORY " + this.getCode() + ", '" + this.getLabel() + "', " + entityName);
2836
            reloadWorkspaceEntities();
2837

    
2838
            EntityRow lentity = this.getWorkspaceEntityByName(entityName);
2839
            if (lentity == null) {
2840
                status.message("Can't find table '" + entityName + "'");
2841
                status.abort();
2842
                return ERR_ENTITY_NOT_EXISTS;
2843
            }
2844
            VarsTable varsTable = new VarsTable();
2845

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

    
2848
            status.message("Executing history request");
2849
            VCSGisHistoryRequest request = this.getRepository().createHistoryRequest(entityName);
2850
            transaction.add(request);
2851

    
2852
            request.setAuthenticationToken(this.authenticationToken);
2853
            request.setUserCode(this.currentUser);
2854
            request.setDateRange(null, null);
2855
            request.setMaxNumberOfRevisions(maxNumberOfRevisions);
2856
            request.setRevisionNumberRange(-1, minRevision);
2857

    
2858
            if ( execute(request) != ERR_OK) {
2859
                status.message("Can't retriev history of " + entityName + " (error " + request.getLastErrorCode() + ")");
2860
                status.abort();
2861
                return request.getLastErrorCode();
2862
            }
2863
            FeatureStore localRevisionsStore = this.openFeatureStore(LocalRevisionsTable.TABLE_NAME);
2864
            transaction.add(localRevisionsStore);
2865
            localRevisionsStore.edit(MODE_PASS_THROUGH);
2866

    
2867
            DisposableIterable<VCSGisRevision> revisions = request.getRevisions();
2868
            status.message("Adding to local revisions");
2869
//            long sz = ContainerUtils.size64(revisions);
2870
//            status.setRangeOfValues(0, sz);
2871
            status.setCurValue(0);
2872

    
2873
            errcode = ERR_CANT_INSERT_FEATURES;
2874
            minRevision = -1;
2875
            Timestamp minDate = now();
2876
            for (VCSGisRevision revision : revisions) {
2877
                LocalRevisionRow row = new LocalRevisionRow(this);
2878
                row.copyFrom(revision);
2879
                row.setGroup(group);
2880
                if (!row.exists(localRevisionsStore)) {
2881
                    row.insert(localRevisionsStore);
2882
                }
2883
                if (minRevision < 0 || minRevision > row.getNumber()) {
2884
                    minRevision = row.getNumber();
2885
                }
2886
                if (minDate.compareTo(row.getRevisionDate()) > 0) {
2887
                    minDate = row.getRevisionDate();
2888
                }
2889
                status.incrementCurrentValue();
2890
            }
2891
            localRevisionsStore.finishEditing();
2892

    
2893
            varsTable.set(
2894
                    this,
2895
                    "history_" + entityName + "_" + group + "_MinDate",
2896
                    minDate.toString()
2897
            );
2898
            varsTable.set(
2899
                    this,
2900
                    "history_" + entityName + "_" + group + "_MinRevision",
2901
                    String.valueOf(minRevision)
2902
            );
2903

    
2904
            transaction.commit();
2905
            status.message("history completed");
2906
            status.terminate();
2907
            return ERR_OK;
2908
        } catch (Exception ex) {
2909
            LOGGER.warn("Can't retrieve history.", ex);
2910
            transaction.rollbackQuietly();
2911
            status.message("Can't retrieve history");
2912
            status.abort();
2913
            return errcode;
2914
        } finally {
2915
            transaction.dispose();
2916
        }
2917
    }
2918

    
2919
    @Override
2920
    public GetItemWithSize64<VCSGisRevision> getRevisions(String entityName, String group) {
2921
        LocalRevisionsTable localRevisionsTable = new LocalRevisionsTable();
2922
        reloadWorkspaceEntities();
2923

    
2924
        VCSGisEntity lentity = this.getEntity(entityName);
2925
        if (lentity == null) {
2926
            throw new IllegalArgumentException("EntityName '" + entityName + "' not found.");
2927
        }
2928
        final VCSGisWorkspaceImpl workspace = this;
2929
        final GetItemWithSizeAndIterator64<Feature> revisionsf = localRevisionsTable.getRevisions(this, lentity.getEntityCode(), group);
2930
        GetItemWithSize64<VCSGisRevision> revisions = new GetItemWithSize64<VCSGisRevision>() {
2931
            @Override
2932
            public long size64() {
2933
                return revisionsf.size64();
2934
            }
2935

    
2936
            @Override
2937
            public VCSGisRevision get64(long position) {
2938
                Feature f = revisionsf.get64(position);
2939
                LocalRevisionRow revision = new LocalRevisionRow(workspace, f);
2940
                return revision;
2941
            }
2942
        };
2943
        return revisions;
2944
    }
2945

    
2946
    @Override
2947
    public String getUserName(String userCode) {
2948
        return null;
2949
    }
2950

    
2951
    @Override
2952
    public VCSGisUser getUser(String userCode) {
2953
        return null;
2954
    }
2955

    
2956
    @Override
2957
    public Feature getRelatedFeature(VCSGisEntity entity, String featureCode) {
2958
        try {
2959
            FeatureStore store = this.getFeatureStore(entity.getEntityName());
2960
            Feature f = store.findFirst("\"" + entity.getFeatureIdFieldName() + "\"='" + featureCode + "'");
2961
            return f;
2962
        } catch (Exception ex) {
2963
            throw new RuntimeException("Can't retrieve feature '" + entity.getEntityName() + "/" + code + "'.", ex);
2964
        }
2965

    
2966
    }
2967

    
2968
    @Override
2969
    public Feature getRelatedFeature(VCSGisRepositoryChange change) {
2970
        EntityRow entity = this.getWorkspaceEntity(change.getEntityCode());
2971
        return getRelatedFeature(entity, change.getRelatedFeatureCode());
2972
    }
2973
    
2974
    @Override
2975
    public int removeEntity(String nameOrCode) {
2976
        int err = ERR_NO_ERROR;
2977
        EntityRow entity = this.getWorkspaceEntity(nameOrCode);
2978
        if(entity == null){
2979
            err = ERR_ENTITY_NOT_EXISTS;
2980
            return err;
2981
        }
2982

    
2983
        DataTransaction transaction = DALLocator.getDataManager().createTransaction();
2984
        try {
2985
            LOGGER.debug("===: REMOVE ENTITY " + entity.getEntityName());
2986

    
2987

    
2988
            //Eliminamos todos los cambios de esta entidad
2989
            err = ERR_CANT_REMOVE_CHANGES;
2990
            FeatureStore changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
2991
            transaction.add(changesStore);
2992
            changesStore.edit(MODE_FULLEDIT);
2993
            changesStore.delete("\""+WorkspaceChangesTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
2994
            changesStore.finishEditing();
2995

    
2996
            FeatureStore remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
2997
            transaction.add(remoteChangesStore);
2998
            remoteChangesStore.edit(MODE_FULLEDIT);
2999
            remoteChangesStore.delete("\""+RemoteChangesTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3000
            remoteChangesStore.finishEditing();
3001

    
3002
            //Eliminamos las revisiones locales
3003
            FeatureStore revisionsStore = openFeatureStore(LocalRevisionsTable.TABLE_NAME);       
3004
            transaction.add(revisionsStore);
3005
            revisionsStore.edit(MODE_FULLEDIT);
3006
            revisionsStore.delete("\""+LocalRevisionsTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3007
            revisionsStore.finishEditing();
3008
            err = ERR_CANT_REMOVE_ENTITY;
3009

    
3010

    
3011
            //Eliminamos la entidad
3012
            FeatureStore entitiesStore = openFeatureStore(EntitiesTable.TABLE_NAME);       
3013
            transaction.add(entitiesStore);
3014
            entitiesStore.edit(MODE_FULLEDIT);
3015
            entitiesStore.delete("\""+EntitiesTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3016
            entitiesStore.finishEditing();
3017
            err = ERR_CANT_REMOVE_ENTITY;
3018

    
3019

    
3020
            //Eliminamos el DALFILE
3021
            FeatureStore store = this.openFeatureStore(entity);
3022
            if(store != null){
3023
                transaction.add(store);
3024
                ResourcesStorage resourcesStorage = store.getResourcesStorage();
3025
                if (resourcesStorage != null) {
3026
                    Resource resource = resourcesStorage.getResource("dal");
3027
                    if (resource != null) {
3028
                        resourcesStorage.remove(resource.getName());
3029
                    }
3030
                }
3031
            
3032
                //Eliminamos el store
3033
                transaction.add(this.wsexplorer, false);
3034
                this.wsexplorer.remove(store.getParameters());
3035
            }
3036
            
3037
            forceReloadWorkspaceEntities();
3038
            transaction.commit();
3039
            return ERR_OK;
3040
        } catch (Exception ex) {
3041
            LOGGER.warn("Can't remove entity.", ex);
3042
            transaction.rollbackQuietly();
3043
            return err;
3044
        } finally {
3045
            transaction.dispose();
3046
        }
3047
        
3048
    }
3049

    
3050
    public int authenticate(String userId, String password, SimpleTaskStatus status) {
3051
        int errcode = ERR_OK;
3052
        if (status == null) {
3053
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
3054
                    "Authenticate-" + userId
3055
            );
3056
            status.setAutoremove(true);
3057
            status.add();
3058
        }
3059
        try {
3060
            VCSGisAuthenticateRequest request = this.getRepository().createAuthenticateRequest(userId, password);
3061
            if ( execute(request) != ERR_OK) {
3062
                status.message(request.getLastErrorMessage());
3063
                status.abort();
3064
                return request.getLastErrorCode();
3065
            }
3066
            VarsTable varsTable = new VarsTable();
3067
            varsTable.set(this,"USER",request.getUserCode());
3068
            varsTable.set(this,"AUTHENTICATIONTOKEN",request.getAuthenticationToken());
3069
            this.currentUser = request.getUserCode();
3070
            this.authenticationToken = request.getAuthenticationToken();
3071
            status.message("Authentication completed");
3072
            status.terminate();
3073
            return ERR_OK;
3074
        } catch (Exception ex) {
3075
            LOGGER.warn("Can't authenticate user.", ex);
3076
            status.message("Can't authenticate user");
3077
            status.abort();
3078
            return errcode;
3079
        }
3080
    }
3081

    
3082
    @Override
3083
    public void setUserIdentificationRequester(VCSGisUserIdentificationRequester userIdentificationRequester) {
3084
        this.userIdentificationRequester = userIdentificationRequester;
3085
    }
3086

    
3087
    private int execute(VCSGisRequest request) {
3088
        while(true) {
3089
            switch(request.execute()) {
3090
                case ERR_CANT_AUTHENTICATE_USER:
3091
                case ERR_INVALID_AUTHENTICATION_TOKEN:
3092
                case ERR_USER_NOT_AUTHORIZED:
3093
                case ERR_AUTHENTICATION_EXPIRED:
3094
                case ERR_INVALID_USERCODE:
3095
                    if( this.userIdentificationRequester!= null ) {
3096
                        if( this.userIdentificationRequester.requestIdentification() ) {
3097
                            int r = this.authenticate(this.userIdentificationRequester.getUserId(), this.userIdentificationRequester.getPassword(), null);
3098
                            if(r == ERR_OK){
3099
                                request.setAuthenticationToken(this.authenticationToken);
3100
                                request.setUserCode(this.currentUser);
3101
                            }
3102
                            continue;
3103
                        }
3104
                    }
3105
                default:
3106
                    return request.getLastErrorCode();            
3107
            }
3108
        }
3109
    }
3110

    
3111

    
3112
    // TODO: eliminar la constante y contains para usar las de tools.
3113
    public static final Comparator<String> EQUALS_IGNORECASE_COMPARATOR = (Comparator<String>) (String o1, String o2) -> StringUtils.compareIgnoreCase(o1, o2);
3114
    public static boolean contains(Collection collection, Object value, Comparator comparator) {
3115
        for (Object item : collection) {
3116
            if( comparator.compare(item, value)==0 ) {
3117
                return true;
3118
            }
3119
        }
3120
        return false;
3121
    }
3122

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

    
3219
                        target.insert(editableTargetFeature);
3220
                        lastRevisionDate=sourceFeature.getTimestamp(fieldDateName);                       
3221
                    }
3222
                
3223
                }else{
3224
                    EditableFeature ef = targetFeature.getEditable();
3225
                    ef.copyFrom(sourceFeature);
3226
                    ef.setUpdatable(true);
3227
                    target.update(ef);
3228
                }
3229
                status.incrementCurrentValue();
3230
            }
3231
            result = this.commit(lastRevisionDate, lastRevisionDate, null, null);
3232
            if (result!=ERR_OK){
3233
                return result;
3234
            }
3235
            target.finishEditing();
3236
            status.terminate();
3237
            return ERR_OK;
3238
        }catch(Exception ex){
3239
            status.abort();
3240
            return -1;
3241
        }finally{
3242
            DisposeUtils.disposeQuietly(features);
3243
            DisposeUtils.disposeQuietly(target);
3244
        }
3245
    }
3246
    public int revert(String nameOrCode) {
3247
        return revert(nameOrCode, null);
3248
    }
3249
    
3250
    @Override
3251
    public int revert(String nameOrCode, SimpleTaskStatus status) {
3252
        if (status == null) {
3253
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Commit");
3254
            status.setAutoremove(true);
3255
            status.add();
3256
        }
3257

    
3258
//        FeatureStore entitiesStore = null;
3259

    
3260
        DataTransaction transaction = null;
3261
        try {
3262
            LOGGER.debug("===: REVERT " + this.getCode() + ", " + this.getLabel() + ", " + nameOrCode);
3263
            transaction = DALLocator.getDataManager().createTransaction();
3264
            transaction.begin();
3265
            
3266
            status.message("Reverting");
3267
            
3268
            EntityRow entity = this.getWorkspaceEntity(nameOrCode);
3269
            WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
3270
            FeatureStore userStore = null;
3271
            FeatureStore changesStore = null;
3272
//            String dataCodeFieldName = entity.getFeatureIdFieldName();
3273

    
3274
            DisposableFeatureSetIterable changes = changesTable.getSelectedsByEntityCodeAsIterator(this, entity.getEntityCode());
3275
            transaction.add(changes);
3276

    
3277

    
3278
            if (!changes.isEmpty()) {
3279
                userStore = this.openFeatureStore(entity);
3280
                transaction.add(userStore, true);
3281
                userStore.edit(MODE_PASS_THROUGH);
3282
                changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
3283
                transaction.add(changesStore, true);
3284
                changesStore.edit(MODE_PASS_THROUGH);
3285

    
3286
                status.setCurValue(0);
3287
                status.setRangeOfValues(0, changes.size64());
3288
                for (Feature feature : changes) {
3289
                    WorkspaceChangeRow change = new WorkspaceChangeRow(this, feature);
3290
                    change.revert(userStore, changesStore);
3291
//                    String data = change.getData();
3292
//                    JsonObject dataAsJson = change.getDataAsJson();
3293
//                    int operation = change.getOperation();
3294
//                    switch (change.getOperation()) {
3295
//                        case OP_ADD_ENTITY:
3296
//                            //TODO: remove entity ???
3297
////                            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
3298
////                            transaction.add(entitiesStore);
3299
////                            entitiesStore.edit(MODE_PASS_THROUGH);
3300
//                            break;
3301
//                        case OP_INSERT:
3302
//                            // Remove related feature
3303
//                            LOGGER.debug("===: REVERT: insert");
3304
//                            userStore.delete("\"" + dataCodeFieldName + "\"='" + change.getRelatedFeatureCode() + "'");
3305
//                            break;
3306
//                        case OP_UPDATE:
3307
//                            // Update related feature from old feature
3308
//                            Feature relatedFeature = change.getRelatedFeature();
3309
//                            EditableFeature ef = relatedFeature.getEditable();
3310
//                            ef.copyFrom(change.getDataAsJson());
3311
//                            userStore.update(ef);
3312
//                            break;
3313
//                        case OP_DELETE:
3314
//                            //Create new feature from old feature
3315
//                            JsonObject dataJson = change.getDataAsJson();
3316
//                            ef = userStore.createNewFeature(dataJson);
3317
//                            userStore.insert(ef);
3318
//                            break;
3319
//                    }
3320
                    status.incrementCurrentValue();
3321
                }
3322
                userStore.finishEditing();
3323
                changesStore.finishEditing();
3324
            }
3325
            
3326

    
3327
//            LOGGER.debug("===: REVERT: clean local changes");
3328
//            status.message("Removing local list of changes");
3329
//            changesTable.deleteSelectedsByEntity(this, entity.getEntityCode());
3330

    
3331
            status.message("Revert completed");
3332
            status.terminate();
3333
            return ERR_NO_ERROR;
3334
        } catch (Exception ex) {
3335
            LOGGER.warn("Can't revert changes.", ex);
3336
            status.message("Can't revert changes");
3337
            status.abort();
3338
            return ERR_CANT_REVERT;
3339
        } finally {
3340
            DisposeUtils.disposeQuietly(transaction);
3341
        }
3342
    }
3343
    
3344
    @Override
3345
    public int export(String entityName, String tableName, String revisionCode, Timestamp efectiveDate, SimpleTaskStatus status) {
3346
        FeatureStore target = null;
3347
        FeatureStore entitiesStore = null;
3348
        int errcode = ERR_OK;
3349
        VCSGisCheckoutRequest request = null;
3350
        if (status == null) {
3351
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("_Export");
3352
            status.setAutoremove(true);
3353
            status.add();
3354
        }
3355
        try {
3356
            LOGGER.debug("===: EXPORT " + this.getCode() + ", '" + this.getLabel() + "', " + tableName);
3357
            status.message("Preparing export");
3358
            VCSGisEntity lentity = this.getEntity(entityName);
3359
            if (lentity == null) {
3360
                status.message("Table " + tableName + " not exists");
3361
                status.abort();
3362
                return ERR_ENTITY_NOT_EXISTS;
3363
            }
3364
            reloadRepositoryEntities(status);
3365
            request = this.getRepository().createCheckoutRequest(entityName);
3366
            request.setAuthenticationToken(this.authenticationToken);
3367
            request.setUserCode(this.currentUser);
3368
            request.setEfectiveDate(efectiveDate);
3369
            request.setRevisionCode(revisionCode);
3370

    
3371
            status.message("Executing export request for " + tableName);
3372
            if ( execute(request) != ERR_OK) {
3373
                status.message("Can't export " + tableName + " (error " + request.getLastErrorCode() + ")");
3374
                status.abort();
3375
                return request.getLastErrorCode();
3376
            }
3377
            status.message("Updating " + tableName + " metadata");
3378
//            VCSGisEntity rentity = request.getEntity();
3379
//            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
3380
//            entitiesStore.edit(FeatureStore.MODE_FULLEDIT);
3381
//            VCSGisEntity rentity = request.getEntity();
3382
//            lentity = new EntityRow(this);
3383
//            rentity.copyto(lentity);
3384
//            lentity.insert(entitiesStore);
3385
//            LOGGER.debug("===: CHECKOUT " + this.getCode() + ", '" + this.getLabel() + "', " + tableName + ", rev." + rentity.getRepositoryRevisionCode());
3386

    
3387
//            this.forceReloadWorkspaceEntities();
3388
            status.message("Creating table " + tableName);
3389
            this.create_table(lentity, tableName);
3390

    
3391
            status.message("Adding features in " + tableName);
3392
            errcode = ERR_CANT_OPEN_STORE;
3393
            target = this.openFeatureStore(tableName);
3394
            this.addStoreIgnoreChanges(target);
3395
            DisposableIterable<VCSGisRepositoryData> data = request.getData();
3396
//            long sz = ContainerUtils.size64(data); // Con tablas tochas esto deja frita la app.
3397
//            status.setRangeOfValues(0, sz);
3398
            status.setCurValue(0);
3399
            errcode = ERR_CANT_INSERT_FEATURES;
3400
            target.edit(FeatureStore.MODE_APPEND);
3401
            for (VCSGisRepositoryData d : data) {
3402
                EditableFeature f = target.createNewFeature(d.getDataAsJson());
3403
                target.insert(f);
3404
                status.incrementCurrentValue();
3405
            }
3406
            target.finishEditing();
3407

    
3408
            status.message("Updating " + tableName + " metadata");
3409
//            if(StringUtils.isBlank(revisionCode)){
3410
//                lentity.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
3411
//            } else {
3412
//                lentity.setLocalRevisionCode(revisionCode);
3413
//            }
3414
//            lentity.update(entitiesStore);
3415
//            entitiesStore.finishEditing();
3416
//            this.forceReloadWorkspaceEntities();
3417
            request.dispose();
3418

    
3419
            status.message("Export completed");
3420
            status.terminate();
3421
            return ERR_NO_ERROR;
3422
        } catch (Exception ex) {
3423
            LOGGER.warn("Can't export.", ex);
3424
            status.message("Can't export");
3425
            status.abort();
3426
            if (target != null) {
3427
                target.cancelEditingQuietly();
3428
            }
3429
            if (entitiesStore != null) {
3430
                entitiesStore.cancelEditingQuietly();
3431
            }
3432
            return errcode;
3433
        } finally {
3434
            DisposeUtils.disposeQuietly(request);
3435
            if (target != null) {
3436
                this.removeStoreIgnoreChanges(target);
3437
            }
3438
            DisposeUtils.disposeQuietly(target);
3439
            DisposeUtils.disposeQuietly(entitiesStore);
3440

    
3441
        }
3442
    }
3443
}