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

History | View | Annotate | Download (153 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.MutableLong;
21
import org.apache.commons.lang3.mutable.MutableObject;
22
import org.gvsig.expressionevaluator.ExpressionBuilder;
23
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
24
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
25
import org.gvsig.expressionevaluator.ExpressionUtils;
26
import org.gvsig.fmap.dal.DALLocator;
27
import org.gvsig.fmap.dal.DataManager;
28
import org.gvsig.fmap.dal.DataTransaction;
29
import org.gvsig.fmap.dal.OpenDataStoreParameters;
30
import org.gvsig.fmap.dal.exception.DataException;
31
import org.gvsig.fmap.dal.feature.EditableFeature;
32
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
33
import org.gvsig.fmap.dal.feature.EditableFeatureType;
34
import org.gvsig.fmap.dal.feature.Feature;
35
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
36
import org.gvsig.fmap.dal.feature.FeatureQuery;
37
import org.gvsig.fmap.dal.feature.FeatureReference;
38
import org.gvsig.fmap.dal.feature.FeatureSet;
39
import org.gvsig.fmap.dal.feature.FeatureSet.DisposableFeatureSetIterable;
40
import org.gvsig.fmap.dal.feature.FeatureStore;
41
import static org.gvsig.fmap.dal.feature.FeatureStore.MODE_APPEND;
42
import static org.gvsig.fmap.dal.feature.FeatureStore.MODE_FULLEDIT;
43
import static org.gvsig.fmap.dal.feature.FeatureStore.MODE_PASS_THROUGH;
44
import org.gvsig.fmap.dal.feature.FeatureType;
45
import org.gvsig.fmap.dal.store.jdbc.JDBCNewStoreParameters;
46
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorerParameters;
47
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
48
import org.gvsig.fmap.dal.store.jdbc2.JDBCServerExplorer;
49
import org.gvsig.json.Json;
50
import org.gvsig.tools.ToolsLocator;
51
import org.gvsig.tools.dataTypes.DataTypes;
52
import org.gvsig.tools.dispose.DisposableIterable;
53
import org.gvsig.tools.dispose.DisposeUtils;
54
import org.gvsig.tools.i18n.I18nManager;
55
import org.gvsig.tools.logger.FilteredLogger;
56
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
57
import org.gvsig.tools.resourcesstorage.ResourcesStorage.Resource;
58
import org.gvsig.tools.swing.api.ChangeListenerHelper;
59
import org.gvsig.tools.swing.api.ChangeListenerSupport;
60
import org.gvsig.tools.swing.api.ToolsSwingLocator;
61
import org.gvsig.tools.task.SimpleTaskStatus;
62
import org.gvsig.tools.util.GetItemWithSize64;
63
import org.gvsig.tools.util.GetItemWithSizeAndIterator64;
64
import org.gvsig.vcsgis.lib.DisposableIterableAdapter;
65
import org.gvsig.vcsgis.lib.VCSGisChange;
66
import org.gvsig.vcsgis.lib.VCSGisCodeGenerator;
67
import org.gvsig.vcsgis.lib.VCSGisEntity;
68
import static org.gvsig.vcsgis.lib.VCSGisManager.DEFAULT_DATA_TABLE;
69
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_AUTHENTICATION_EXPIRED;
70
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANCELLED_BY_USER;
71
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_ADD_CHANGE;
72
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_AUTHENTICATE_USER;
73
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_COMMIT;
74
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_INSERT_CHANGE;
75
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_INSERT_FEATURES;
76
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_OPEN_CHANGES;
77
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_OPEN_ENTITIES;
78
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_OPEN_STORE;
79
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_PREPARE_UPDATE;
80
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_REMOVE_CHANGES;
81
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_REMOVE_ENTITY;
82
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_RETRIEVE_ENTITIES;
83
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_RETRIEVE_SOURCE_FEATURES;
84
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_REVERT;
85
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_UPDATE;
86
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_UPDATE_CLEAN;
87
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_UPDATE_ENTITIES;
88
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_ENTITY_ALREADY_EXISTS;
89
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_ENTITY_NOT_EXISTS;
90
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_ENTITY_NOT_HAS_VCSGISCODE;
91
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_INVALID_AUTHENTICATION_TOKEN;
92
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_INVALID_USERCODE;
93
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_NO_ERROR;
94
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_OK;
95
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_STORE_NOT_IN_VERSION_CONTROL;
96
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_UPDATE_NEED_MERGE;
97
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_USER_NOT_AUTHORIZED;
98
import static org.gvsig.vcsgis.lib.VCSGisManager.FEATURECODE_FIELD_NAME;
99
import static org.gvsig.vcsgis.lib.VCSGisManager.OP_ADD_ENTITY;
100
import static org.gvsig.vcsgis.lib.VCSGisManager.OP_DELETE;
101
import static org.gvsig.vcsgis.lib.VCSGisManager.OP_INSERT;
102
import static org.gvsig.vcsgis.lib.VCSGisManager.OP_UPDATE;
103
import static org.gvsig.vcsgis.lib.VCSGisManager.STATE_CONFLICT;
104
import static org.gvsig.vcsgis.lib.VCSGisManager.STATE_LOCAL_MODIFIED;
105
import static org.gvsig.vcsgis.lib.VCSGisManager.STATE_LOCAL_NEW;
106
import static org.gvsig.vcsgis.lib.VCSGisManager.STATE_LOCAL_OUTDATED;
107
import static org.gvsig.vcsgis.lib.VCSGisManager.STATE_LOCAL_OUTDATED_AND_MODIFIED;
108
import static org.gvsig.vcsgis.lib.VCSGisManager.STATE_LOCAL_UNMODIFIED;
109
import static org.gvsig.vcsgis.lib.VCSGisManager.VCSGISCODELEN;
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.VCSGisUserIdentificationRequester;
116
import org.gvsig.vcsgis.lib.VCSGisUtils;
117
import org.gvsig.vcsgis.lib.repository.VCSGisRepository;
118
import org.gvsig.vcsgis.lib.repository.VCSGisRepositoryChange;
119
import org.gvsig.vcsgis.lib.repository.VCSGisRepositoryData;
120
import org.gvsig.vcsgis.lib.repository.localdb.VCSGisRepositoryLocaldb;
121
import org.gvsig.vcsgis.lib.repository.localdb.tables.EntitiesRepoTable;
122
import org.gvsig.vcsgis.lib.repository.requests.VCSGisAuthenticateRequest;
123
import org.gvsig.vcsgis.lib.repository.requests.VCSGisCheckoutRequest;
124
import org.gvsig.vcsgis.lib.repository.requests.VCSGisCommitRequest;
125
import org.gvsig.vcsgis.lib.repository.requests.VCSGisEntitiesRequest;
126
import org.gvsig.vcsgis.lib.repository.requests.VCSGisHistoryRequest;
127
import org.gvsig.vcsgis.lib.repository.requests.VCSGisRequest;
128
import org.gvsig.vcsgis.lib.repository.requests.VCSGisTopologyPlansRequest;
129
import org.gvsig.vcsgis.lib.repository.requests.VCSGisUpdateRequest;
130
import org.gvsig.vcsgis.lib.repository.requests.VCSGisUsersRequest;
131
import org.gvsig.vcsgis.lib.workspace.tables.EntitiesTable;
132
import org.gvsig.vcsgis.lib.workspace.tables.EntitiesTable.EntityRow;
133
import org.gvsig.vcsgis.lib.workspace.tables.LocalRevisionsTable;
134
import org.gvsig.vcsgis.lib.workspace.tables.LocalRevisionsTable.LocalRevisionRow;
135
import org.gvsig.vcsgis.lib.workspace.tables.RemoteChangesTable;
136
import static org.gvsig.vcsgis.lib.workspace.tables.RemoteChangesTable.COD_ENTITY;
137
import org.gvsig.vcsgis.lib.workspace.tables.RemoteChangesTable.RemoteChangeRow;
138
import org.gvsig.vcsgis.lib.workspace.tables.TopologyplanTable;
139
import org.gvsig.vcsgis.lib.workspace.tables.UsersTable;
140
import org.gvsig.vcsgis.lib.workspace.tables.VarsTable;
141
import org.gvsig.vcsgis.lib.workspace.tables.WorkspaceChangesTable;
142
import org.gvsig.vcsgis.lib.workspace.tables.WorkspaceChangesTable.WorkspaceChangeRow;
143
import org.slf4j.Logger;
144
import org.slf4j.LoggerFactory;
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 currentUserCode;
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.currentUserCode = 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.currentUserCode = 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 OpenDataStoreParameters createOpenStoreParameters(String tableName) {
619
        try {
620
            JDBCStoreParameters params = this.wsexplorer.get(tableName);
621
            return params;
622
        } catch (Exception ex) {
623
            LOGGER.trace("can't create open store parameters from '" + this.getMessageLabel() + "'.", ex);
624
            return null;
625
        }
626
    }
627

    
628
    @Override
629
    public String createUniqueCode() {
630
        return this.codeGenerator.generateCode();
631
    }
632

    
633
    @Override
634
    public String getErrorMessage(int errcode) {
635
        return VCSGisUtils.getErrorMessage(errcode);
636
    }
637

    
638
    @Override
639
    public int addChange(int operation, FeatureStore userStore, Feature feature) {
640
        String entityName = StoreProperties.getEntityName(userStore);
641
        if (StringUtils.isBlank(entityName)) {
642
            return ERR_STORE_NOT_IN_VERSION_CONTROL;
643
        }
644
        if (this.isInStoreIgnoreChanges(userStore)) {
645
            LOGGER.debug("===: ADD_CHANGE: Skip (" + userStore.getName() + ")");
646
            return ERR_NO_ERROR;
647
        }
648
        EntityRow entity = this.getWorkspaceEntityByName(entityName);
649
        FeatureStore changesStore = this.getFeatureStore(WorkspaceChangesTable.TABLE_NAME);
650
        try {
651
            changesStore.edit(MODE_PASS_THROUGH);
652
            return addChange(entity, operation, changesStore, feature, userStore.getOriginalFeature(feature));
653
        } catch (Exception ex) {
654
            LOGGER.warn("Can't add change (op " + VCSGisUtils.getOperationLabel(operation) + ", " + entity.getEntityName() + ")", ex);
655
            changesStore.cancelEditingQuietly();
656
            return ERR_CANT_ADD_CHANGE;
657
        } finally {
658
            changesStore.finishEditingQuietly();
659
            DisposeUtils.dispose(changesStore);
660
        }
661
    }
662

    
663
    private int addChange(VCSGisWorkspaceEntity entity, int operation, FeatureStore changesStore, Feature feature, Feature oldFeature) {
664
        try {
665
            String featureCode = feature.getString(entity.getFeatureIdFieldName());
666
            Feature previousChange = changesStore.findFirst(WorkspaceChangesTable.FEATUREID + " = '" + featureCode + "'"); // and " + WorkspaceChangesTable.OPERATION+ " = " + operation);
667
            if (previousChange != null) {
668
                int previousOperation = previousChange.getInt(WorkspaceChangesTable.OPERATION);
669
                /*
670
                operation - previo
671
                INS - INS -> Error
672
                INS - UPD -> Error
673
                INS - DEL -> Error
674
                UPD - INS -> no hace nada y sale con OK
675
                UPD - UPD -> no hace nada y sale con OK
676
                UPD - DEL -> Error
677
                 */
678
                switch (operation) {
679
                    case OP_INSERT:
680
                        return ERR_CANT_ADD_CHANGE;
681
                    case OP_UPDATE:
682
                        switch (previousOperation) {
683
                            case OP_INSERT:
684
                            case OP_UPDATE:
685
                                return ERR_OK;
686
                            case OP_DELETE:
687
                                return ERR_CANT_ADD_CHANGE;
688
                            default:
689
                                return ERR_OK;
690
                        }
691

    
692
                }
693

    
694
                return ERR_OK;
695
            }
696

    
697
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, changesStore.createNewFeature());
698
            change.newCode();
699
            change.setEntityCode(entity.getEntityCode());
700
            change.setFeatureCode(featureCode);
701
            change.setOperation(operation);
702
            change.setLabel(feature.getString(entity.getFieldForLabel()));
703
            if(oldFeature != null){
704
                change.setData(oldFeature.toJson().toString());
705
            }
706
            change.setSelected(true);
707
            switch (operation) {
708
                case OP_INSERT:
709
                    change.setStatus(STATE_LOCAL_NEW);
710
                    break;
711
                case OP_UPDATE:
712
                    change.setStatus(STATE_LOCAL_MODIFIED);
713
                    break;
714
            }
715

    
716
            change.insert(changesStore);
717
            return ERR_OK;
718
        } catch (Exception ex) {
719
            LOGGER.warn("Can't add change (op " + VCSGisUtils.getOperationLabel(operation) + ", " + entity.getEntityName() + ")", ex);
720
            return ERR_CANT_ADD_CHANGE;
721
        }
722
    }
723

    
724
    private int addDeleteChange(VCSGisWorkspaceEntity entity, FeatureStore changesStore, String featureCode, String label, Feature oldFeature) {
725
        try {
726
            WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
727
            WorkspaceChangeRow previousChange = changesTable.find(this, changesStore, entity.getEntityCode(), featureCode);
728
            if (previousChange != null) {
729
                
730
                /*
731
                DEL - INS -> Quitar el insert y salir con OK
732
                DEL - UPD -> Quitar el update y meter delete (continuar)
733
                DEL - DEL -> Error
734
                 */
735
                switch (previousChange.getOperation()) {
736
                    case OP_INSERT:
737
                        previousChange.delete(changesStore);
738
                        return ERR_OK;
739
                    case OP_UPDATE:
740
                    default:
741
                        previousChange.setOperation(OP_DELETE);
742
                        previousChange.setSelected(true);
743
                        previousChange.update();
744
                        break;
745

    
746
                    case OP_DELETE:
747
                        return ERR_CANT_ADD_CHANGE;
748
                }
749
            }
750

    
751
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, changesStore.createNewFeature());
752
            change.newCode();
753
            change.setEntityCode(entity.getEntityCode());
754
            change.setFeatureCode(featureCode);
755
            change.setOperation(OP_DELETE);
756
            change.setLabel(label);
757
            if(oldFeature != null){
758
                change.setData(oldFeature.toJson().toString());
759
            }
760
            change.setSelected(true);
761
            change.setStatus(STATE_LOCAL_MODIFIED);
762
            change.insert(changesStore);
763
            return ERR_OK;
764
        } catch (Exception ex) {
765
            LOGGER.warn("Can't add delete change (" + entity.getEntityName() + ")", ex);
766
            return ERR_CANT_ADD_CHANGE;
767
        }
768
    }
769

    
770
    @Override
771
    public int addEntity(FeatureType featureType, String name, String description, String fieldForLabel) {
772
        return this.addEntity(featureType, name, description, fieldForLabel, null, null, null);
773
    }
774

    
775
    @Override
776
    public int addEntity(FeatureType featureType, String name, String description, String fieldForLabel, String category, String label, String pkName) {
777
        FeatureStore store = null;
778
        int err = ERR_NO_ERROR;
779
        try {
780
            LOGGER.debug("===: ADD_ENTITY " + this.getCode() + ", '" + this.getLabel() + "', " + name);
781
            EditableFeatureType ft = featureType.getCopy().getEditable();
782

    
783
            for (FeatureAttributeDescriptor attr : ft.getPrimaryKey()) {
784
                EditableFeatureAttributeDescriptor editAttr = (EditableFeatureAttributeDescriptor) attr;
785
                editAttr.setIsPrimaryKey(false);
786
                editAttr.setAllowNull(false);
787
                editAttr.setIsIndexed(true);
788
                editAttr.setAllowIndexDuplicateds(false);
789
            }
790

    
791
            EditableFeatureAttributeDescriptor attr = (EditableFeatureAttributeDescriptor) ft.getAttributeDescriptor(FEATURECODE_FIELD_NAME);
792
            if (attr == null) {
793
                err = ERR_ENTITY_NOT_HAS_VCSGISCODE;
794
                ft.add(FEATURECODE_FIELD_NAME, DataTypes.STRING)
795
                        .setSize(VCSGISCODELEN)
796
                        .setIsPrimaryKey(true)
797
                        .setIsIndexed(true)
798
                        .setAllowIndexDuplicateds(false)
799
                        .setLabel("VCSGIS Code");
800
                ft.setHasOID(false);
801
            } else {
802
                if (!attr.isPrimaryKey()) {
803
                    attr.setIsPrimaryKey(true);
804
                    ft.setHasOID(false);
805
                }
806
            }
807

    
808
            EditableFeatureAttributeDescriptor geomattr = (EditableFeatureAttributeDescriptor) ft.getDefaultGeometryAttribute();
809
            if( geomattr!=null ) {
810
                geomattr.setIsIndexed(true);
811
            }
812

    
813
            featureType = ft.getNotEditableCopy();
814
            if (featureType.getAttributeDescriptor(fieldForLabel) == null) {
815
                FeatureAttributeDescriptor[] pk = featureType.getPrimaryKey();
816
                if (pk == null || pk.length < 1) {
817
                    fieldForLabel = featureType.getAttributeName(0);
818
                } else {
819
                    fieldForLabel = pk[0].getName();
820
                }
821
            }
822

    
823
            err = ERR_CANT_OPEN_ENTITIES;
824
            EntityRow entity = new EntityRow(this);
825
            entity.newCode();
826
            entity.setEntityName(name);
827
            entity.setDataTableName(DEFAULT_DATA_TABLE);
828
            entity.setFeatureIdFieldName(FEATURECODE_FIELD_NAME);
829
            entity.setGeometryFieldName(featureType.getDefaultGeometryAttributeName());
830
            entity.setDescription(description);
831
            entity.setFieldForLabel(fieldForLabel);
832
            entity.setFeatureTypeAsJson(featureType.toJsonBuilder().toString());
833
            entity.setLocalRevisionCode(null);
834
            entity.setRepositoryRevisionCode(null);
835
            entity.setCategory(category);
836
            entity.setLabel(label);
837
            entity.setState(STATE_LOCAL_NEW);
838
            entity.insert();
839

    
840
            this.forceReloadWorkspaceEntities();
841
            err = ERR_CANT_INSERT_CHANGE;
842

    
843
            entity = this.getWorkspaceEntityByName(name);
844
            FeatureStore changesStore = this.getFeatureStore(WorkspaceChangesTable.TABLE_NAME);
845
//            addChange(entity, OP_ADD_ENTITY, changesStore, null, null);
846

    
847
            WorkspaceChangeRow change = new WorkspaceChangeRow(this);
848
            change.newCode();
849
            change.setEntityCode(entity.getCode());
850
            change.setFeatureCode(null);
851
            change.setOperation(OP_ADD_ENTITY);
852
            change.setSelected(true);
853
            change.insert();
854

    
855
            this.create_table(entity);
856

    
857
        } catch (VCSGisRuntimeException ex) {
858
            LOGGER.warn("can't add entity '" + name + "'.", ex);
859
            if (store != null) {
860
                store.cancelEditingQuietly();
861
            }
862
            return ex.getErrnum();
863
        } catch (Exception ex) {
864
            LOGGER.warn("can't add entity '" + name + "'.", ex);
865
            if (store != null) {
866
                store.cancelEditingQuietly();
867
            }
868
            return err;
869
        } finally {
870
            DisposeUtils.disposeQuietly(store);
871
        }
872
        return ERR_NO_ERROR;
873
    }
874

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

    
991
    @Override
992
    public int add(String name, FeatureStore source, String fieldForLabel) {
993
        return this.add(name, source, fieldForLabel, null, null, null, null);
994
    }
995

    
996
    @Override
997
    public int add(String name, FeatureStore source, String fieldForLabel, String category, String label) {
998
        return this.add(name, source, fieldForLabel, category, label, null, null);
999
    }
1000

    
1001
    @Override
1002
    public int add(String name, FeatureStore source, String fieldForLabel, String category, String label, String pkName, SimpleTaskStatus status) {
1003
        if (isInMyDatabase(source)) {
1004
            return addExistingTable(name, source, fieldForLabel, category, label, pkName, status);
1005
        } else {
1006
            return addNewTable(name, source, fieldForLabel, category, label, pkName, status);
1007
        }
1008

    
1009
    }
1010

    
1011
    private int addNewTable(String name, FeatureStore source, String fieldForLabel, String category, String label, String pkName, SimpleTaskStatus status) {
1012
        if (this.getEntity(name) != null) { // is in VCS
1013
            return ERR_ENTITY_ALREADY_EXISTS;
1014
        }
1015
        I18nManager i18n = ToolsLocator.getI18nManager();
1016
        if (status == null) {
1017
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(i18n.getTranslation("_Add_layer"));
1018
            status.setAutoremove(true);
1019
            status.add();
1020
        }
1021

    
1022
        FeatureStore target = null;
1023
        FeatureSet srcFeatures = null;
1024
        int errcode = ERR_NO_ERROR;
1025
        DataTransaction transaction = null;
1026
        try {
1027
            transaction = DALLocator.getDataManager().createTransaction();
1028
            transaction.begin();
1029
            LOGGER.debug("===: ADD " + this.getCode() + ", '" + this.getLabel() + "', " + name);
1030
            EntityRow entity = this.getWorkspaceEntityByName(name);
1031
            if (entity != null) {
1032
                return ERR_ENTITY_ALREADY_EXISTS;
1033
            }
1034
            status.message(i18n.getTranslation("_Adding_table_layer"));
1035
            FeatureType ft = source.getDefaultFeatureTypeQuietly();
1036
            errcode = this.addEntity(ft, name, null, fieldForLabel, category, label, pkName);
1037
            if (errcode != ERR_NO_ERROR) {
1038
                transaction.rollbackQuietly();
1039
                return errcode;
1040
            }
1041
            errcode = ERR_CANT_OPEN_STORE;
1042
            target = this.openFeatureStore(name);
1043
            transaction.add(target);
1044
            errcode = ERR_CANT_RETRIEVE_SOURCE_FEATURES;
1045
            status.message(i18n.getTranslation("_Preparing_source"));
1046
            srcFeatures = source.getFeatureSet();
1047
            transaction.add(srcFeatures);
1048
            errcode = ERR_CANT_INSERT_FEATURES;
1049
            target.edit(MODE_APPEND);
1050

    
1051
            FeatureStore changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
1052
            transaction.add(changesStore);
1053
            changesStore.edit(MODE_APPEND);
1054

    
1055
            this.addStoreIgnoreChanges(target);
1056
            entity = this.getWorkspaceEntityByName(name);
1057

    
1058
            status.message(null);
1059
            status.setRangeOfValues(0, srcFeatures.size64());
1060
            status.setCurValue(0);
1061
            for (Feature srcFeature : srcFeatures) {
1062
                EditableFeature targetFeature;
1063
                String featureCode = this.createUniqueCode();
1064
                targetFeature = target.createNewFeature(srcFeature);
1065
                targetFeature.set(FEATURECODE_FIELD_NAME, featureCode);
1066
                target.insert(targetFeature);
1067

    
1068
                WorkspaceChangeRow change = new WorkspaceChangeRow(this);
1069
                change.newCode();
1070
                change.setEntityCode(entity.getEntityCode());
1071
                change.setFeatureCode(featureCode);
1072
                change.setOperation(OP_INSERT);
1073
                change.setLabel(targetFeature.getString(entity.getFieldForLabel()));
1074
                change.setSelected(true);
1075
                change.setStatus(STATE_LOCAL_NEW);
1076
                change.insert(changesStore);
1077

    
1078
                status.incrementCurrentValue();
1079
                if (status.isCancellationRequested()) {
1080
                    transaction.rollbackQuietly();
1081
                    status.cancel();
1082
                    return ERR_CANCELLED_BY_USER;
1083
                }
1084
            }
1085
            status.message(i18n.getTranslation("_Finishing"));
1086
            target.finishEditing();
1087
            transaction.commit();
1088
            status.terminate();
1089
            return ERR_NO_ERROR;
1090
        } catch (Exception ex) {
1091
            LOGGER.warn("Can't add features to '" + name + "' in '" + this.getMessageLabel() + "'.", ex);
1092
            status.abort();
1093
            DataTransaction.rollbackQuietly(transaction);
1094
            return errcode;
1095
        } finally {
1096
            DisposeUtils.disposeQuietly(transaction);
1097
        }
1098
    }
1099

    
1100
    private int addExistingTable(String name, FeatureStore source, String fieldForLabel, String category, String label, String pkName, SimpleTaskStatus status) {
1101
        if (this.getEntity(name) != null) { // is in VCS
1102
            return ERR_ENTITY_ALREADY_EXISTS;
1103
        }
1104
        DataManager dataManager = DALLocator.getDataManager();
1105
        I18nManager i18n = ToolsLocator.getI18nManager();
1106
        if (status == null) {
1107
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(i18n.getTranslation("_Add_layer"));
1108
            status.setAutoremove(true);
1109
            status.add();
1110
        }
1111

    
1112
        FeatureStore target = null;
1113
        FeatureSet targetFeatures = null;
1114
        int errcode = ERR_NO_ERROR;
1115
        DataTransaction transaction = null;
1116
        try {
1117
            JDBCServerExplorer explorer = (JDBCServerExplorer) dataManager.openServerExplorer(this.getProviderName(), this.getExplorerParameters());
1118
            transaction = dataManager.createTransaction();
1119
            transaction.begin();
1120
            transaction.add(explorer);
1121
            LOGGER.debug("===: ADD " + this.getCode() + ", '" + this.getLabel() + "', " + name);
1122
            EntityRow entity = this.getWorkspaceEntityByName(name);
1123
            if (entity != null) {
1124
                return ERR_ENTITY_ALREADY_EXISTS;
1125
            }
1126
            status.message(i18n.getTranslation("_Adding_table_layer"));
1127

    
1128
            FeatureType featureType = source.getDefaultFeatureType();
1129
            FeatureAttributeDescriptor attr = featureType.getAttributeDescriptor(FEATURECODE_FIELD_NAME);
1130
            if (attr == null) {
1131
//                explorer.execute("ALTER TABLE \""+name+"\" ADD COLUMN \""+FEATURECODE_FIELD_NAME+"\" VARCHAR(40)");
1132
                explorer.execute(
1133
                        String.format(
1134
                                VCSGisUtils.getSqlTemplate(explorer.getProviderName(), "alterTableAddColumnVCSGISCODE"),
1135
                                name
1136
                        )
1137
                );
1138
            }
1139

    
1140
            ResourcesStorage resourcesStorage = source.getResourcesStorage();
1141
            if (resourcesStorage != null) {
1142
                Resource resource = resourcesStorage.getResource("dal");
1143
                if (resource != null) {
1144
                    resourcesStorage.remove(resource.getName());
1145
                }
1146
            }
1147

    
1148
            target = (FeatureStore) dataManager.openStore(source.getProviderName(), source.getParameters());
1149

    
1150
            transaction.add(target);
1151
            errcode = ERR_CANT_RETRIEVE_SOURCE_FEATURES;
1152
            status.message(i18n.getTranslation("_Preparing_source"));
1153
            targetFeatures = target.getFeatureSet();
1154
            transaction.add(targetFeatures);
1155
            errcode = ERR_CANT_INSERT_FEATURES;
1156
            target.edit(MODE_PASS_THROUGH);
1157

    
1158
            FeatureStore changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
1159
            transaction.add(changesStore);
1160
            changesStore.edit(MODE_APPEND);
1161

    
1162
            FeatureStore entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1163
            transaction.add(entitiesStore);
1164
            entitiesStore.edit(MODE_FULLEDIT);
1165

    
1166
            this.addStoreIgnoreChanges(target);
1167
//            entity = this.getWorkspaceEntityByName(name);
1168
            errcode = ERR_CANT_OPEN_ENTITIES;
1169
            entity = new EntityRow(this);
1170
            entity.newCode();
1171
            entity.setEntityName(name);
1172
            entity.setDataTableName(DEFAULT_DATA_TABLE);
1173
            entity.setFeatureIdFieldName(FEATURECODE_FIELD_NAME);
1174
            entity.setGeometryFieldName(featureType.getDefaultGeometryAttributeName());
1175
            entity.setDescription(null);
1176
            entity.setFieldForLabel(fieldForLabel);
1177
            entity.setFeatureTypeAsJson(featureType.toJsonBuilder().toString());
1178
            entity.setLocalRevisionCode(null);
1179
            entity.setRepositoryRevisionCode(null);
1180
            entity.setState(STATE_LOCAL_NEW);
1181
            entity.setCategory(category);
1182
            entity.setLabel(label);
1183
            entity.insert(entitiesStore);
1184
            entitiesStore.finishEditing();
1185

    
1186
            this.forceReloadWorkspaceEntities();
1187
            errcode = ERR_CANT_INSERT_CHANGE;
1188

    
1189
            entity = this.getWorkspaceEntityByName(name);
1190

    
1191
//            addChange(entity, OP_ADD_ENTITY, changesStore, null, null);
1192
            WorkspaceChangeRow change = new WorkspaceChangeRow(this);
1193
            change.newCode();
1194
            change.setEntityCode(entity.getCode());
1195
            change.setFeatureCode(null);
1196
            change.setOperation(OP_ADD_ENTITY);
1197
            change.setSelected(true);
1198
            change.insert(changesStore);
1199

    
1200
            status.message(null);
1201
            status.setRangeOfValues(0, targetFeatures.size64());
1202
            status.setCurValue(0);
1203
            for (Feature targetFeature : targetFeatures) {
1204
                EditableFeature editableFeature;
1205
                String featureCode = this.createUniqueCode();
1206

    
1207
                editableFeature = targetFeature.getEditable();
1208
                editableFeature.set(FEATURECODE_FIELD_NAME, featureCode);
1209
                targetFeatures.update(editableFeature);
1210

    
1211
                change = new WorkspaceChangeRow(this);
1212
                change.newCode();
1213
                change.setEntityCode(entity.getEntityCode());
1214
                change.setFeatureCode(featureCode);
1215
                change.setOperation(OP_INSERT);
1216
                change.setLabel(editableFeature.getString(entity.getFieldForLabel()));
1217
                change.setSelected(true);
1218
                change.setStatus(STATE_LOCAL_NEW);
1219
                change.insert(changesStore);
1220

    
1221
                status.incrementCurrentValue();
1222
                if (status.isCancellationRequested()) {
1223
                    transaction.rollbackQuietly();
1224
                    status.cancel();
1225
                    return ERR_CANCELLED_BY_USER;
1226
                }
1227
            }
1228

    
1229
            target.finishEditing();
1230

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

    
1239
//            explorer.execute("ALTER TABLE \""+name+"\" ALTER COLUMN \""+FEATURECODE_FIELD_NAME+"\" SET NOT NULL");
1240
            explorer.execute(
1241
                    String.format(
1242
                            VCSGisUtils.getSqlTemplate(explorer.getProviderName(), "alterTableAlterColumnVCSGISCODESetNotNull"),
1243
                            entity.getEntityName()
1244
                    )
1245
            );
1246

    
1247
//            explorer.execute("ALTER TABLE \""+name+"\" ADD PRIMARY KEY (\""+FEATURECODE_FIELD_NAME+"\")");
1248
            explorer.execute(
1249
                    String.format(
1250
                            VCSGisUtils.getSqlTemplate(explorer.getProviderName(), "alterTableAddPrimaryKeyVCSGISCODE"),
1251
                            entity.getEntityName()
1252
                    )
1253
            );
1254

    
1255
            target = (FeatureStore) dataManager.openStore(source.getProviderName(), source.getParameters());
1256

    
1257
            EditableFeatureType ft = target.getDefaultFeatureTypeQuietly().getEditable();
1258
            EditableFeatureAttributeDescriptor geomattr = (EditableFeatureAttributeDescriptor) ft.getDefaultGeometryAttribute();
1259
            if( geomattr!=null ) {
1260
                geomattr.setIsIndexed(true);
1261
            }
1262

    
1263
            entitiesStore.edit(MODE_FULLEDIT);
1264

    
1265
            entity.setFeatureTypeAsJson(ft.toJsonBuilder().toString());
1266
            entity.update(entitiesStore);
1267

    
1268
            entitiesStore.finishEditing();
1269

    
1270
            status.message(i18n.getTranslation("_Finishing"));
1271
            transaction.commit();
1272
            status.terminate();
1273
            return ERR_NO_ERROR;
1274
        } catch (Exception ex) {
1275
            LOGGER.warn("Can't add features to '" + name + "' in '" + this.getMessageLabel() + "'.", ex);
1276
            status.abort();
1277
            DataTransaction.rollbackQuietly(transaction);
1278
            return errcode;
1279
        } finally {
1280
            DisposeUtils.disposeQuietly(transaction);
1281
        }
1282
    }
1283

    
1284
    @Override
1285
    public VCSGisWorkspaceChanges<VCSGisWorkspaceChange> getLocalChanges() {
1286
        return getLocalChanges(null);
1287
    }
1288

    
1289
    @Override
1290
    public VCSGisWorkspaceChanges<VCSGisWorkspaceChange> getLocalChanges(List<VCSGisEntity> entities) {
1291
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1292
        ChangesImpl changes = new ChangesImpl<WorkspaceChangeRow>(changesTable.getByEntityCode(this, entities), WorkspaceChangesTable.SELECTED) {
1293
            @Override
1294
            protected WorkspaceChangeRow createChange(Feature f) {
1295
                return new WorkspaceChangeRow(VCSGisWorkspaceImpl.this, f);
1296
            }
1297

    
1298
            @Override
1299
            protected void updateChange(FeatureStore store, WorkspaceChangeRow change) {
1300
                change.update(store);
1301
            }
1302

    
1303
        };
1304
        return changes;
1305
    }
1306

    
1307
//    @Override
1308
//    public VCSGisWorkspaceChanges<VCSGisWorkspaceChange> getLocalChangesByEntityCodeOrName(String codeOrName) {
1309
//        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1310
//        ChangesImpl changes = new ChangesImpl<WorkspaceChangeRow>(changesTable.getByEntityCode(this, codeOrName), WorkspaceChangesTable.SELECTED) {
1311
//            @Override
1312
//            protected WorkspaceChangeRow createChange(Feature f) {
1313
//                return new WorkspaceChangeRow(VCSGisWorkspaceImpl.this, f);
1314
//            }
1315
//
1316
//            @Override
1317
//            protected void updateChange(FeatureStore store, WorkspaceChangeRow change) {
1318
//                change.update(store);
1319
//            }
1320
//
1321
//        };
1322
//        return changes;
1323
//    }
1324

    
1325
//    @Override
1326
//    public VCSGisWorkspaceChanges<VCSGisWorkspaceChange> getLocalChangesByEntityName(String entityName) {
1327
//        EntityRow entity = this.getWorkspaceEntityByName(entityName);
1328
//        return getLocalChangesByEntityCode(entity.getEntityCode());
1329
//    }
1330
//
1331
//    @Override
1332
//    public VCSGisWorkspaceChanges<VCSGisWorkspaceChange> getLocalChangesByEntityCode(String entityCode) {
1333
//        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1334
//        ChangesImpl changes = new ChangesImpl<WorkspaceChangeRow>(changesTable.getByEntityCode(this,entityCode),WorkspaceChangesTable.SELECTED) {
1335
//            @Override
1336
//            protected WorkspaceChangeRow createChange(Feature targetFeature) {
1337
//                return new WorkspaceChangeRow(VCSGisWorkspaceImpl.this, targetFeature);
1338
//            }
1339
//
1340
//            @Override
1341
//            protected void updateChange(FeatureStore store, WorkspaceChangeRow change) {
1342
//                change.update(store);
1343
//            }
1344
//
1345
//        };
1346
//        return changes;
1347
//    }
1348
    @Override
1349
    public VCSGisRepository getRepository() {
1350
        return repository;
1351
    }
1352

    
1353
    @Override
1354
    public List<VCSGisEntity> getEntitiesOfRemoteChanges() {
1355
        ArrayList<VCSGisEntity> res = new ArrayList<>();
1356
        RemoteChangesTable changesTable = new RemoteChangesTable();
1357
        DisposableFeatureSetIterable features = changesTable.getGroupedByEntity(this);
1358
        EntitiesRepoTable entitiesRepoTable = new EntitiesRepoTable();
1359
        for (Feature feature : features) {
1360
            VCSGisEntity entity = entitiesRepoTable.getByEntityCode((VCSGisRepositoryLocaldb) this.getRepository(), feature.getString(RemoteChangesTable.COD_ENTITY));
1361
            res.add(entity);
1362
        }
1363
        DisposeUtils.disposeQuietly(features);
1364
        return res;
1365
    }
1366

    
1367
    @Override
1368
    public VCSGisWorkspaceChanges<VCSGisRepositoryChange> getRemoteChanges() {
1369
        return getRemoteChangesByEntity(null);
1370
    }
1371

    
1372
    @Override
1373
    public VCSGisWorkspaceChanges<VCSGisRepositoryChange> getRemoteChangesByEntity(String entityName) {
1374
        String entityCode;
1375
        if (StringUtils.isBlank(entityName)) {
1376
            entityCode = null;
1377
        } else {
1378
            VCSGisEntity entity = this.getWorkspaceEntity(entityName);
1379
            if (entity == null) {
1380
                entity = this.getRepositoryEntity(entityName);
1381
                if (entity == null) {
1382
                    return null;
1383
                }
1384
            }
1385
            entityCode = entity.getEntityCode();
1386
        }
1387
        RemoteChangesTable changesTable = new RemoteChangesTable();
1388
        ChangesImpl changes = new ChangesImpl<RemoteChangeRow>(changesTable.getByEntityCode(this, entityCode), RemoteChangesTable.SELECTED) {
1389
            @Override
1390
            protected RemoteChangeRow createChange(Feature f) {
1391
                return new RemoteChangeRow(VCSGisWorkspaceImpl.this, f);
1392
            }
1393

    
1394
            @Override
1395
            protected void updateChange(FeatureStore store, RemoteChangeRow change) {
1396
                change.update(store);
1397
            }
1398

    
1399
        };
1400
        return changes;
1401
    }
1402

    
1403
    private Timestamp now() {
1404
        return Timestamp.from(LocalDateTime.now().toInstant(ZoneOffset.UTC));
1405
    }
1406

    
1407
    public List<VCSGisEntity> getEntitiesOfLocalChanges() {
1408
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1409
        List<VCSGisEntity> entities = new ArrayList<>();
1410

    
1411
        DisposableFeatureSetIterable changesGroupedByEntity = changesTable.getGroupedByEntity(this);
1412
        
1413
        for (Feature fchange : changesGroupedByEntity) {
1414
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1415
            VCSGisEntity localEntity = change.getEntity();
1416
            if (change.isSelected()) {
1417
                entities.add(localEntity);
1418
            }
1419
        }
1420
        return entities;  
1421
    }
1422
    
1423
    @SuppressWarnings("Convert2Lambda")
1424
    public boolean prepareCommitRequest(VCSGisCommitRequest request, List<String> entityCodes, Timestamp revisiondate, Timestamp efectivedate, String comment, SimpleTaskStatus status) {
1425
        boolean isMyStatus = false;
1426
        if (status == null) {
1427
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Prepare commit request");
1428
            status.setAutoremove(true);
1429
            status.add();
1430
            isMyStatus = true;
1431
        }
1432
        request.setEfectiveDate(efectivedate);
1433
        request.setRevisionDate(revisiondate);
1434
        request.setComment(comment);
1435
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1436

    
1437
        LOGGER.debug("===: COMMIT: Adding changed local entities");
1438
        status.message("Searching changed entities");
1439
        // adicionamos las entidades que vamos a actualizar con las revisiones que tenemos.
1440
        DisposableFeatureSetIterable changesGroupedByEntity = changesTable.getGroupedByEntity(this);
1441
//        status.setRangeOfValues(0, changesGroupedByEntity.size64());
1442
        status.setCurValue(0);
1443
        for (Feature fchange : changesGroupedByEntity) {
1444
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1445
            VCSGisWorkspaceEntity localEntity = change.getEntity();
1446
            LOGGER.debug("===: COMMIT: add used entity = " + fchange.toJson().toString().replace('\n', ' '));
1447
            if (change.isSelected()) {
1448
                if(CollectionUtils.isEmpty(entityCodes) || entityCodes.contains(localEntity.getEntityCode())){
1449
                    request.add(request.createEntity(localEntity));
1450
                }
1451
            }
1452
            status.incrementCurrentValue();
1453
        }
1454
        changesGroupedByEntity.dispose();
1455

    
1456
        LOGGER.debug("===: COMMIT: Mark new local entities");
1457
        status.message("Searching new entities");
1458
        // Marcamos como nuevas las entidades que se han dado de alta.
1459
        DisposableFeatureSetIterable changesOfAddEntities = changesTable.getByOperation(this, OP_ADD_ENTITY);
1460
        for (Feature fchange : changesOfAddEntities) {
1461
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1462
            if (change.isSelected()) {
1463
                if(CollectionUtils.isEmpty(entityCodes) || entityCodes.contains(change.getEntityCode())){
1464
                    request.markAsNew(change.getEntity());
1465
                }
1466
            }
1467
        }
1468
        changesOfAddEntities.dispose();
1469

    
1470
        LOGGER.debug("===: COMMIT: Adding data");
1471
        status.message("Searching changed data");
1472
        // adicionamos los datos
1473
        boolean useSeleccion = true;
1474
        DisposableFeatureSetIterable changes = changesTable.getSelectedsWithoutAddEntity(this, entityCodes);
1475
        if (changes != null) {
1476
            request.add(new DisposableIterableAdapter(
1477
                    changes,
1478
                    new DisposableIterableAdapter.ItemConverter<Feature, VCSGisChange>() {
1479
                @Override
1480
                public VCSGisChange convert(Feature f) {
1481
                    return new WorkspaceChangeRow(VCSGisWorkspaceImpl.this, f);
1482
                }
1483
            }
1484
            )
1485
            );
1486
        }
1487
        if (isMyStatus) {
1488
            status.terminate();
1489
        }
1490
        return useSeleccion;
1491
    }
1492

    
1493
    @Override
1494
    public boolean canCommit() {
1495
        return canCommit(null);
1496
    }
1497

    
1498
    @Override
1499
    public boolean canCommit(MutableObject<String> message) {
1500
        return canCommit(message, null);
1501
    }
1502

    
1503
    @Override
1504
    public boolean canCommit(MutableObject<String> message, List<String> entityCodes) {
1505

    
1506
        List<String> outdatedEntityNames = new ArrayList<>();
1507
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1508
        DisposableFeatureSetIterable changesGroupedByEntity = null;
1509
        try {
1510

    
1511
            changesGroupedByEntity = changesTable.getGroupedByEntity(this);
1512
            for (Feature fchange : changesGroupedByEntity) {
1513
                WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1514
                VCSGisWorkspaceEntity entity = change.getEntity();
1515
                if(CollectionUtils.isEmpty(entityCodes) || entityCodes.contains(entity.getEntityCode())){
1516
                    LOGGER.debug("===: CAN-COMMIT: add used entity = " + fchange.toJson().toString().replace('\n', ' '));
1517
                    if (change.isSelected() && entity.isOutdated()) {
1518
                        outdatedEntityNames.add(entity.getEntityName());
1519
                    }
1520
                }
1521
            }
1522
            DisposeUtils.dispose(changesGroupedByEntity);
1523

    
1524
            if (!outdatedEntityNames.isEmpty()) {
1525
                if (message != null) {
1526
                    I18nManager i18n = ToolsLocator.getI18nManager();
1527
                    String msg = i18n.getTranslation("_Tables_in_working_copy_are_outdated")
1528
                            + ". ("
1529
                            + StringUtils.join(outdatedEntityNames, ", ")
1530
                            + ")";
1531
                    message.setValue(msg);
1532
                }
1533
                return false;
1534
            }
1535
            return true;
1536
        } catch (Exception ex) {
1537
            return false;
1538
        } finally {
1539
            DisposeUtils.dispose(changesGroupedByEntity);
1540
        }
1541
    }
1542

    
1543
    @Override
1544
    public List<VCSGisWorkspaceEntity> getEntitiesWithSelectedChanges() {
1545

    
1546
        List<VCSGisWorkspaceEntity> entities = new ArrayList<>();
1547
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1548
        DisposableFeatureSetIterable changesGroupedByEntity = null;
1549
        try {
1550

    
1551
            changesGroupedByEntity = changesTable.getGroupedByEntity(this);
1552
            for (Feature fchange : changesGroupedByEntity) {
1553
                WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
1554
                VCSGisWorkspaceEntity entity = change.getEntity();
1555
                if (change.isSelected()) {
1556
                    entities.add(entity);
1557
                }
1558
            }
1559
            return entities;
1560

    
1561
        } catch (Exception ex) {
1562
            return null;
1563
        } finally {
1564
            DisposeUtils.dispose(changesGroupedByEntity);
1565
        }
1566
    }
1567

    
1568
    @Override
1569
    public int commit() {
1570
        return commit(null, null, now(), null, null);
1571
    }
1572

    
1573
    @Override
1574
    public int commit(Timestamp efectivedate, String comment, SimpleTaskStatus status) {
1575
        return commit(null, null, efectivedate, comment, status);
1576
    }
1577

    
1578
    @Override
1579
    public int commit(Timestamp revisiondate, Timestamp efectivedate, String comment, SimpleTaskStatus status) {
1580
        return commit(null, revisiondate, efectivedate, comment, status);
1581
    }
1582

    
1583
    @Override
1584
    @SuppressWarnings("Convert2Lambda")
1585
    public int commit(List<String> entityCodes, Timestamp revisiondate, Timestamp efectivedate, String comment, SimpleTaskStatus status) {
1586
        VCSGisCommitRequest request = null;
1587
        if (status == null) {
1588
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Commit");
1589
            status.setAutoremove(true);
1590
            status.add();
1591
        }
1592
        try {
1593
            LOGGER.debug("===: COMMIT " + this.getCode() + ", " + this.getLabel());
1594
            EntitiesTable entitiesTable = new EntitiesTable();
1595
            WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1596

    
1597
            status.message("Preparing commit");
1598
            reloadRepositoryEntities(status);
1599
            request = this.getRepository().createCommitRequest();
1600
            request.setAuthenticationToken(this.authenticationToken);
1601
            request.setUserCode(this.currentUserCode);
1602

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

    
1605
            LOGGER.debug("===: COMMIT: Do execute request");
1606
            status.message("Executing commit request");
1607
            if ( execute(request) != ERR_OK) {
1608
                status.message("Can't commit changes (error " + request.getLastErrorCode() + ")");
1609
                status.abort();
1610
                return request.getLastErrorCode();
1611
            }
1612

    
1613
            LOGGER.debug("===: COMMIT: update local entities table");
1614
            status.message("Updating local metadata");
1615
            FeatureStore entitiesStore = null;
1616
            try {
1617
                entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1618
                entitiesStore.edit(FeatureStore.MODE_FULLEDIT);
1619
                List<VCSGisWorkspaceEntity> changedLocalentities = request.getChangedLocalEntities();
1620
                status.setRangeOfValues(0, changedLocalentities.size());
1621
                status.setCurValue(0);
1622
                for (VCSGisEntity rentity : changedLocalentities) {
1623
                    EntityRow entityRow = entitiesTable.getByEntityName(this, rentity.getEntityName());
1624
                    if (entityRow != null) {
1625
                        entityRow.copyfrom(rentity);
1626
                        entityRow.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
1627
                        entityRow.update(entitiesStore);
1628
                    }
1629
                    status.incrementCurrentValue();
1630
                }
1631
                entitiesStore.finishEditing();
1632
                forceReloadWorkspaceEntities();
1633
            } catch (Exception e) {
1634
                FeatureStore.cancelEditingQuietly(entitiesStore);
1635
            } finally {
1636
                DisposeUtils.disposeQuietly(entitiesStore);
1637
                entitiesStore = null;
1638
            }
1639

    
1640
            LOGGER.debug("===: COMMIT: clean local changes");
1641
            status.message("Removing local list of changes");
1642
            if (useSeleccion) {
1643
                changesTable.deleteSelecteds(this, entityCodes);
1644
            } else {
1645
                changesTable.deleteAll(this);
1646
            }
1647
            status.message("Commit completed");
1648
            status.terminate();
1649
            return ERR_NO_ERROR;
1650
        } catch (Exception ex) {
1651
            LOGGER.warn("Can't commit changes.", ex);
1652
            status.message("Can't commit changes");
1653
            status.abort();
1654
            return ERR_CANT_COMMIT;
1655
        } finally {
1656
            DisposeUtils.disposeQuietly(request);
1657
        }
1658
    }
1659
    
1660

    
1661
    @Override
1662
    public int checkout(String tableName) {
1663
        return checkout(tableName, null);
1664
    }
1665

    
1666
    @Override
1667
    public int checkout(String tableName, String revisionCode) {
1668
        return checkout(tableName, revisionCode, null);
1669
    }
1670

    
1671
    @Override
1672
    public int checkout(String tableName, String revisionCode, SimpleTaskStatus status) {
1673
        FeatureStore target = null;
1674
        FeatureStore entitiesStore = null;
1675
        int errcode = ERR_OK;
1676
        VCSGisCheckoutRequest request = null;
1677
        if (status == null) {
1678
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("_Checkout");
1679
            status.setAutoremove(true);
1680
            status.add();
1681
        }
1682
        try {
1683
            LOGGER.debug("===: CHECKOUT " + this.getCode() + ", '" + this.getLabel() + "', " + tableName);
1684
            status.message("Preparing checkout");
1685
            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
1686
            if (lentity != null) {
1687
                status.message("Table " + tableName + " already exists");
1688
                status.abort();
1689
                return ERR_ENTITY_ALREADY_EXISTS;
1690
            }
1691
            reloadRepositoryEntities(status);
1692
            request = this.getRepository().createCheckoutRequest(tableName);
1693
            request.setAuthenticationToken(this.authenticationToken);
1694
            request.setUserCode(this.currentUserCode);
1695
            request.setEfectiveDate((Timestamp) null);
1696
            request.setRevisionCode(revisionCode);
1697

    
1698
            status.message("Executing checkout request for " + tableName);
1699
            if ( execute(request) != ERR_OK) {
1700
                status.message("Can't checkout " + tableName + " (error " + request.getLastErrorCode() + ")");
1701
                status.abort();
1702
                return request.getLastErrorCode();
1703
            }
1704
            status.message("Updating " + tableName + " metadata");
1705
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1706
            entitiesStore.edit(FeatureStore.MODE_FULLEDIT);
1707
            VCSGisEntity rentity = request.getEntity();
1708
            lentity = new EntityRow(this);
1709
            rentity.copyto(lentity);
1710
            lentity.insert(entitiesStore);
1711
            LOGGER.debug("===: CHECKOUT " + this.getCode() + ", '" + this.getLabel() + "', " + tableName + ", rev." + rentity.getRepositoryRevisionCode());
1712

    
1713
//            this.forceReloadWorkspaceEntities();
1714
            status.message("Creating table " + tableName);
1715
            this.create_table(lentity);
1716

    
1717
            status.message("Adding features in " + tableName);
1718
            errcode = ERR_CANT_OPEN_STORE;
1719
            target = this.openFeatureStore(lentity);
1720
            this.addStoreIgnoreChanges(target);
1721
            DisposableIterable<VCSGisRepositoryData> data = request.getData();
1722
//            long sz = ContainerUtils.size64(data); // Con tablas tochas esto deja frita la app.
1723
//            status.setRangeOfValues(0, sz);
1724
            status.setCurValue(0);
1725
            errcode = ERR_CANT_INSERT_FEATURES;
1726
            target.edit(FeatureStore.MODE_APPEND);
1727
            for (VCSGisRepositoryData d : data) {
1728
                EditableFeature f = target.createNewFeature(d.getDataAsJson());
1729
                target.insert(f);
1730
                status.incrementCurrentValue();
1731
            }
1732
            target.finishEditing();
1733

    
1734
            status.message("Updating " + tableName + " metadata");
1735
            if(StringUtils.isBlank(revisionCode)){
1736
                lentity.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
1737
            } else {
1738
                lentity.setLocalRevisionCode(revisionCode);
1739
            }
1740
            lentity.update(entitiesStore);
1741
            entitiesStore.finishEditing();
1742
            this.forceReloadWorkspaceEntities();
1743
            
1744
            UsersTable usersTable = new UsersTable();
1745
            if( StringUtils.isNotBlank(request.getUsersHashCode()) ) {
1746
                if( !StringUtils.equalsIgnoreCase(usersTable.getHashCode(this), request.getUsersHashCode())) {
1747
                    updateUsersFromRepository(status);
1748
                }
1749
            }
1750
            TopologyplanTable topologyPlansTable = new TopologyplanTable();
1751
            if( StringUtils.isNotBlank(request.getTopologyPlansHashCode()) ) {
1752
                if( !StringUtils.equalsIgnoreCase(topologyPlansTable.getHashCode(this), request.getTopologyPlansHashCode())) {
1753
                    updateTopologyPlansFromRepository(status);
1754
                }
1755
            }
1756
            request.dispose();
1757

    
1758
            status.message("Checkout completed");
1759
            status.terminate();
1760
            return ERR_NO_ERROR;
1761
        } catch (Exception ex) {
1762
            LOGGER.warn("Can't checkout.", ex);
1763
            status.message("Can't checkout");
1764
            status.abort();
1765
            FeatureStore.cancelEditingQuietly(target);
1766
            FeatureStore.cancelEditingQuietly(entitiesStore);
1767
            return errcode;
1768
        } finally {
1769
            DisposeUtils.disposeQuietly(request);
1770
            if (target != null) {
1771
                this.removeStoreIgnoreChanges(target);
1772
            }
1773
            DisposeUtils.disposeQuietly(target);
1774
            DisposeUtils.disposeQuietly(entitiesStore);
1775

    
1776
        }
1777
    }
1778
    
1779
    @Override
1780
    public int checkout(List<String> tableNames, SimpleTaskStatus status){
1781
        for (String tableName : tableNames) {
1782
            int r = checkout(tableName, null, status);
1783
            if(r != ERR_NO_ERROR){
1784
                return r;
1785
            }
1786
        }
1787
        return ERR_NO_ERROR;
1788
    }
1789

    
1790

    
1791
    private void updateUsersFromRepository(SimpleTaskStatus status) {
1792
        FeatureStore usersStore = null;
1793
        VCSGisUsersRequest request = null;
1794
        try {
1795
            request = this.getRepository().createUsersRequest();
1796
            request.setAuthenticationToken(this.authenticationToken);
1797
            request.setUserCode(this.currentUserCode);
1798

    
1799
            status.message("Executing users request");
1800
            if ( execute(request) != ERR_OK) {
1801
                status.message("Can't get users (error " + request.getLastErrorCode() + ")");
1802
                return;
1803
            }
1804
            status.message("Updating users information");
1805
            usersStore = this.openFeatureStore(UsersTable.TABLE_NAME);
1806
            usersStore.edit(FeatureStore.MODE_PASS_THROUGH);
1807
            usersStore.delete("TRUE");
1808
            for (VCSGisUser user : request.getUsers()) {
1809
                UsersTable.UserRow row = new UsersTable.UserRow(this);
1810
                row.copyFrom(user);
1811
                row.insert(usersStore);
1812
            }
1813
            usersStore.finishEditing();
1814
            
1815
        } catch(Exception ex) {
1816
            LOGGER.warn("Can't update users.", ex);
1817
            status.message("Can't update users");
1818
            FeatureStore.cancelEditingQuietly(usersStore);
1819
        } finally {
1820
            DisposeUtils.disposeQuietly(request);
1821
            DisposeUtils.disposeQuietly(usersStore);
1822
        }     
1823
    }
1824
    
1825
    private void updateTopologyPlansFromRepository(SimpleTaskStatus status) {
1826
        FeatureStore topologyPlanStore = null;
1827
        VCSGisTopologyPlansRequest request = null;
1828
        try {
1829
            request = this.getRepository().createTopologyPlansRequest();
1830
            request.setAuthenticationToken(this.authenticationToken);
1831
            request.setUserCode(this.currentUserCode);
1832

    
1833
            status.message("Executing topology plans request");
1834
            if ( execute(request) != ERR_OK) {
1835
                status.message("Can't get topology plans (error " + request.getLastErrorCode() + ")");
1836
                return;
1837
            }
1838
            status.message("Updating topology plans information");
1839
            topologyPlanStore = this.openFeatureStore(TopologyplanTable.TABLE_NAME);
1840
            topologyPlanStore.edit(FeatureStore.MODE_PASS_THROUGH);
1841
            topologyPlanStore.delete("TRUE");
1842
            for (VCSGisTopologyPlan topologyPlan : request.getTopologyPlans()) {
1843
                TopologyplanTable.TopologyPlanRow row = new TopologyplanTable.TopologyPlanRow(this);
1844
                row.copyFrom(topologyPlan);
1845
                row.insert(topologyPlanStore);
1846
            }
1847
            topologyPlanStore.finishEditing();
1848
            
1849
        } catch(Exception ex) {
1850
            LOGGER.warn("Can't update topology plans.", ex);
1851
            status.message("Can't update topology plans");
1852
            FeatureStore.cancelEditingQuietly(topologyPlanStore);
1853
        } finally {
1854
            DisposeUtils.disposeQuietly(request);
1855
            DisposeUtils.disposeQuietly(topologyPlanStore);
1856
        }     
1857
    }
1858
    
1859
    @Override
1860
    public int updateEntitiesFromRepository() {
1861
        return this.updateEntitiesFromRepository(null);
1862
    }
1863

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

    
1878
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1879
            entitiesStore.edit(MODE_FULLEDIT);
1880
            for (VCSGisEntity rentity : this.getRepositoryEntities()) {
1881
                EntityRow entityRow = entitiesTable.getByEntityName(this, rentity.getEntityName());
1882
                if (entityRow != null) {
1883
                    rentity.copyto(entityRow);
1884
                    entityRow.update(entitiesStore);
1885
                }
1886
            }
1887
            entitiesStore.finishEditingQuietly();
1888

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

    
1907
    @Override
1908
    public int updatePrepare(String tableName) {
1909
        return updatePrepare(tableName, null);
1910
    }
1911

    
1912
    @Override
1913
    public int updatePrepare(String tableName, SimpleTaskStatus status) {
1914
        LOGGER.debug("===: UPDATE_PREPARE: " + tableName + " WS " + this.getCode() + ", '" + this.getLabel() + "'");
1915
        if (status == null) {
1916
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Update-prepare " + tableName);
1917
            status.setAutoremove(true);
1918
            status.add();
1919
        }
1920

    
1921
        FeatureStore remoteChangesStore = null;
1922
        VCSGisUpdateRequest request = null;
1923
        DisposableIterable<VCSGisRepositoryData> remoteChanges = null;
1924
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1925
        FeatureStore userStore = null;
1926
        FeatureStore localChangesStore = null;
1927
        FeatureStore entitiesStore = null;
1928
        DataTransaction transaction = null;
1929
        try {
1930
            transaction = DALLocator.getDataManager().createTransaction();
1931
            transaction.begin();
1932
            transaction.add(this.getExplorer(), false);
1933

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

    
1969
            status.message("Preparing remote changes container");
1970
            remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
1971
            transaction.add(remoteChangesStore);
1972
            remoteChangesStore.edit(MODE_PASS_THROUGH);
1973

    
1974
            status.message("Deleting previous temporary remote changes");
1975
            LOGGER.debug("===: UPDATE_PREPARE: Delete updates table");
1976
            remoteChangesStore.delete("\"" + COD_ENTITY + "\"='" + entityCode + "'");
1977

    
1978
            remoteChanges = request.getData();
1979
            transaction.add(remoteChanges);
1980
//            long sz = ContainerUtils.size64(remoteChanges);
1981
//            status.setRangeOfValues(0, sz);
1982
            status.setCurValue(0);
1983

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

    
2015
                if (hasConflictRemoteChangeWithUserTable(lentity, remoteChange, userStore)) {
2016
                    remoteChangeRow.setStatus(STATE_CONFLICT);
2017
                    lentity.setState(STATE_CONFLICT);
2018
                }
2019

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

    
2063
                }
2064
                remoteChangeRow.insert(remoteChangesStore);
2065
                status.incrementCurrentValue();
2066
            }
2067
            LOGGER.debug("===: UPDATE_PREPARE: finish inserting updates");
2068
            lentity.update(entitiesStore);
2069

    
2070
            remoteChangesStore.finishEditing();
2071
            localChangesStore.finishEditing();
2072
            entitiesStore.finishEditing();
2073

    
2074
            updateLocallyModyfiedRemoteChanges();
2075

    
2076
            transaction.commit();
2077

    
2078
            status.message("Update-prepare completed");
2079
            status.terminate();
2080
            return ERR_OK;
2081
        } catch (Exception ex) {
2082
            LOGGER.warn("Can't prepare update.", ex);
2083
            status.message("Can't prepare update");
2084
            status.abort();
2085
            DataTransaction.rollbackQuietly(transaction);
2086
            return ERR_CANT_PREPARE_UPDATE;
2087
        } finally {
2088
            DisposeUtils.disposeQuietly(transaction);
2089
        }
2090

    
2091
    }
2092

    
2093
    private void updateLocallyModyfiedRemoteChanges() {
2094

    
2095
        RemoteChangesTable changes = new RemoteChangesTable();
2096
        changes.updateStateFromLocalChanges(this, STATE_LOCAL_OUTDATED_AND_MODIFIED);
2097

    
2098
    }
2099

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

    
2117
                    Feature f = store.findFirst(builder.toString());
2118
                    if (f != null && !StringUtils.equals(
2119
                            f.getString(lentity.getFeatureIdFieldName()),
2120
                            remoteChange.getFeatureRelatedCode())) {
2121
                        return true;
2122
                    }
2123
                }
2124
            }
2125
        }
2126
        return false;
2127
    }
2128

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

    
2194
        FeatureSet feats = store.getFeatureSet(filter.toString());
2195
        return feats.iterable();
2196
    }
2197

    
2198
    @Override
2199
    public int updateClean(String entityCode) {
2200
        return updateClean(entityCode, null);
2201
    }
2202

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

    
2230
    }
2231

    
2232
    @Override
2233
    public int update(String tableName) {
2234
        return this.update(tableName, false, false, null);
2235
    }
2236

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

    
2242
    @Override
2243
    public int merge(String tableName) {
2244
        return this.update(tableName, false, true, null);
2245
    }
2246

    
2247
    @Override
2248
    public int merge(String tableName, SimpleTaskStatus status) {
2249
        return this.update(tableName, false, true, null, status);
2250
    }
2251
    
2252
    @Override
2253
    public int merge(String tableName, MutableLong localChangesCreated, SimpleTaskStatus status) {
2254
        return this.update(tableName, false, true, localChangesCreated, status);
2255
    }
2256

    
2257
    public int update(String tableName, boolean prepare, boolean merge, SimpleTaskStatus status) {
2258
        return update(tableName, prepare, merge, null, status);
2259
    }
2260

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

    
2283
        EditableFeature ef;
2284
        DisposableFeatureSetIterable remoteChanges = null;
2285

    
2286
        FeatureStore workspaceChangesStore = null;
2287
        FeatureStore remoteChangesStore = null;
2288
        FeatureStore userStore = null;
2289
        FeatureStore entitiesStore = null;
2290

    
2291
        DataTransaction transaction = null;
2292
        try {
2293
            transaction = DALLocator.getDataManager().createTransaction();
2294
            transaction.begin();
2295

    
2296
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
2297
            transaction.add(entitiesStore);
2298
            entitiesStore.edit(MODE_PASS_THROUGH);
2299

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

    
2319
            userStore = this.openFeatureStore(lentity);
2320
            if (userStore == null) {
2321
                this.create_table(lentity);
2322
                userStore = this.openFeatureStore(lentity);
2323
            }
2324
            transaction.add(userStore);
2325
            userStore.edit(MODE_PASS_THROUGH);
2326

    
2327
            workspaceChangesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
2328
            transaction.add(workspaceChangesStore);
2329
            workspaceChangesStore.edit(MODE_PASS_THROUGH);
2330

    
2331
            remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
2332
            transaction.add(remoteChangesStore);
2333
            remoteChangesStore.edit(MODE_PASS_THROUGH);
2334

    
2335
            remoteChanges = remoteChangesTable.getSelectedsByEntityCodeAsIterator(this, lentity.getCode());
2336
            transaction.add(remoteChanges);
2337
//            long sz = ContainerUtils.size64(remoteChanges);
2338
//            status.setRangeOfValues(0, sz);
2339
            status.setCurValue(0);
2340

    
2341
            if (!remoteChanges.isEmpty()) {
2342
                this.addStoreIgnoreChanges(userStore);
2343
                status.message("Updating table (" + lentity.getEntityName() + ")");
2344
                FeatureType type = userStore.getDefaultFeatureTypeQuietly();
2345

    
2346
                ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
2347
                ExpressionBuilder builder = expManager.createExpressionBuilder();
2348

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

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

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

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

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

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

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

    
2460
                                    ef = userStore.createNewFeature(f);
2461
                                    ef.setString(lentity.getFeatureIdFieldName(), this.createUniqueCode());
2462
                                    userStore.insert(ef);
2463

    
2464
                                    workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2465
                                    this.addChange(lentity, OP_INSERT, workspaceChangesStore, ef, null);
2466
                                    localChangesCreated.increment();
2467
                                }
2468
                                break;
2469
                        }
2470
                        status.incrementCurrentValue();
2471
                    }
2472
                }
2473
            }
2474
            localChangesTable.removeLocalChangesRelatedToSelectedRemoteChanges(this, lentity);
2475
            remoteChangesTable.delete(remoteChangesStore, lentity.getEntityCode());
2476

    
2477
            status.message("Updating metadata tables");
2478
            lentity.setLocalRevisionCode(lentity.getRepositoryRevisionCode());
2479
            lentity.update(entitiesStore);
2480
            forceReloadWorkspaceEntities();
2481

    
2482
            transaction.commit();
2483

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

    
2498
    @Override
2499
    public JDBCServerExplorer getExplorer() {
2500
        return this.wsexplorer;
2501
    }
2502

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

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

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

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

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

    
2702
    @Override
2703
    public boolean updateNeedMerge(String entityName) {
2704
        RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2705

    
2706
        VCSGisEntity entity = this.getWorkspaceEntity(entityName);
2707
        if (entity == null) {
2708
            entity = this.getRepositoryEntity(entityName);
2709
        }
2710

    
2711
        return remoteChangesTable.updateNeedMerge(this, entity.getEntityCode());
2712
    }
2713

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

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

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

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

    
2764
            status.message("Executing history request");
2765
            VCSGisHistoryRequest request = this.getRepository().createHistoryRequest(entityName);
2766
            transaction.add(request);
2767

    
2768
            request.setAuthenticationToken(this.authenticationToken);
2769
            request.setUserCode(this.currentUserCode);
2770
            request.setDateRange(minDate, maxDate);
2771
            request.setMaxNumberOfRevisions(maxNumberOfRevisions);
2772
            request.setRevisionNumberRange(-1, -1);
2773

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

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

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

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

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

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

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

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

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

    
2871
            status.message("Executing history request");
2872
            VCSGisHistoryRequest request = this.getRepository().createHistoryRequest(entityName);
2873
            transaction.add(request);
2874

    
2875
            request.setAuthenticationToken(this.authenticationToken);
2876
            request.setUserCode(this.currentUserCode);
2877
            request.setDateRange(null, null);
2878
            request.setMaxNumberOfRevisions(maxNumberOfRevisions);
2879
            request.setRevisionNumberRange(-1, minRevision);
2880

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

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

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

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

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

    
2942
    @Override
2943
    public GetItemWithSize64<VCSGisRevision> getRevisions(String entityName, String group) {
2944
        LocalRevisionsTable localRevisionsTable = new LocalRevisionsTable();
2945
        reloadWorkspaceEntities();
2946

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

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

    
2969
    @Override
2970
    public String getUserName(String userCode) {
2971
        return null;
2972
    }
2973

    
2974
    @Override
2975
    public VCSGisUser getUser(String userCode) {
2976
        return null;
2977
    }
2978

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

    
2989
    }
2990

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

    
3006
        DataTransaction transaction = DALLocator.getDataManager().createTransaction();
3007
        try {
3008
            err = doRemoveEntity(entity, transaction);
3009
            forceReloadWorkspaceEntities();
3010
            transaction.commit();
3011
            return ERR_OK;
3012
        } catch (Exception ex) {
3013
            LOGGER.warn("Can't remove entity.", ex);
3014
            transaction.rollbackQuietly();
3015
            return err;
3016
        } finally {
3017
            transaction.dispose();
3018
        }
3019
    }
3020

    
3021
    @Override
3022
    public int removeEntities(List<String> namesOrCodes) {
3023
        int err = ERR_NO_ERROR;
3024
        DataTransaction transaction = DALLocator.getDataManager().createTransaction();
3025
        
3026
        try {
3027
            for (String nameOrCode : namesOrCodes) {
3028
                EntityRow entity = this.getWorkspaceEntity(nameOrCode);
3029
                if(entity == null){
3030
                    err = ERR_ENTITY_NOT_EXISTS;
3031
                    return err;
3032
                }
3033

    
3034
                doRemoveEntity(entity, transaction);
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
    private int doRemoveEntity(EntityRow entity, DataTransaction transaction) throws DataException {
3051
        int err;
3052
        LOGGER.debug("===: REMOVE ENTITY " + entity.getEntityName());
3053
        //Eliminamos todos los cambios de esta entidad
3054
        err = ERR_CANT_REMOVE_CHANGES;
3055
        FeatureStore changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
3056
        transaction.add(changesStore);
3057
        changesStore.edit(MODE_FULLEDIT);
3058
        changesStore.delete("\""+WorkspaceChangesTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3059
        changesStore.finishEditing();
3060
        FeatureStore remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
3061
        transaction.add(remoteChangesStore);
3062
        remoteChangesStore.edit(MODE_FULLEDIT);
3063
        remoteChangesStore.delete("\""+RemoteChangesTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3064
        remoteChangesStore.finishEditing();
3065
        //Eliminamos las revisiones locales
3066
        FeatureStore revisionsStore = openFeatureStore(LocalRevisionsTable.TABLE_NAME);
3067
        transaction.add(revisionsStore);
3068
        revisionsStore.edit(MODE_FULLEDIT);
3069
        revisionsStore.delete("\""+LocalRevisionsTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3070
        revisionsStore.finishEditing();
3071
        err = ERR_CANT_REMOVE_ENTITY;
3072
        //Eliminamos la entidad
3073
        FeatureStore entitiesStore = openFeatureStore(EntitiesTable.TABLE_NAME);
3074
        transaction.add(entitiesStore);
3075
        entitiesStore.edit(MODE_FULLEDIT);
3076
        entitiesStore.delete("\""+EntitiesTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3077
        entitiesStore.finishEditing();
3078
        err = ERR_CANT_REMOVE_ENTITY;
3079
        //Eliminamos el DALFILE
3080
        FeatureStore store = this.openFeatureStore(entity);
3081
        if(store != null){
3082
            transaction.add(store);
3083
            ResourcesStorage resourcesStorage = store.getResourcesStorage();
3084
            if (resourcesStorage != null) {
3085
                Resource resource = resourcesStorage.getResource("dal");
3086
                if (resource != null) {
3087
                    resourcesStorage.remove(resource.getName());
3088
                }
3089
            }
3090
            
3091
            //Eliminamos el store
3092
            transaction.add(this.wsexplorer, false);
3093
            this.wsexplorer.remove(store.getParameters());
3094
        }
3095
        return err;
3096
    }
3097

    
3098
    @Override
3099
    public boolean authenticate(SimpleTaskStatus status) {
3100
        if( StringUtils.isNotBlank(this.currentUserCode) ) {
3101
            return true;
3102
        }
3103
        int r = authenticate(null, null, status);
3104
        switch (r) {
3105
            case ERR_CANT_AUTHENTICATE_USER:
3106
            case ERR_INVALID_AUTHENTICATION_TOKEN:
3107
            case ERR_USER_NOT_AUTHORIZED:
3108
            case ERR_AUTHENTICATION_EXPIRED:
3109
            case ERR_INVALID_USERCODE:
3110
                if (this.userIdentificationRequester != null) {
3111
                    if (this.userIdentificationRequester.requestIdentification()) {
3112
                        r = this.authenticate(this.userIdentificationRequester.getUserId(), this.userIdentificationRequester.getPassword(), null);
3113
                        if (r == ERR_OK) {
3114
                            return true;
3115
                        }
3116
                    }
3117
                }
3118
                return false;
3119
            default:
3120
                return true;
3121
        }
3122
    }
3123
    
3124
    public int authenticate(String userId, String password, SimpleTaskStatus status) {
3125
        int errcode = ERR_OK;
3126
        if (status == null) {
3127
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
3128
                    "Authenticate-" + userId
3129
            );
3130
            status.setAutoremove(true);
3131
            status.add();
3132
        }
3133
        try {
3134
            VCSGisAuthenticateRequest request = this.getRepository().createAuthenticateRequest(userId, password);
3135
            if ( request.execute() != ERR_OK) {
3136
                status.message(request.getLastErrorMessage());
3137
                status.abort();
3138
                return request.getLastErrorCode();
3139
            }
3140
            VarsTable varsTable = new VarsTable();
3141
            varsTable.set(this,"USER",request.getUserCode());
3142
            varsTable.set(this,"AUTHENTICATIONTOKEN",request.getAuthenticationToken());
3143
            this.currentUserCode = request.getUserCode();
3144
            this.authenticationToken = request.getAuthenticationToken();
3145
            this.getRepository().setAuthenticationToken(request.getAuthenticationToken());
3146
            this.getRepository().setUserCode(request.getUserCode());
3147
            
3148
            status.message("Authentication completed");
3149
            status.terminate();
3150
            return ERR_OK;
3151
        } catch (Exception ex) {
3152
            LOGGER.warn("Can't authenticate user.", ex);
3153
            status.message("Can't authenticate user");
3154
            status.abort();
3155
            return errcode;
3156
        }
3157
    }
3158

    
3159
    @Override
3160
    public void setUserIdentificationRequester(VCSGisUserIdentificationRequester userIdentificationRequester) {
3161
        this.userIdentificationRequester = userIdentificationRequester;
3162
    }
3163

    
3164
    @Override
3165
    public VCSGisUserIdentificationRequester getUserIdentificationRequester() {
3166
        return this.userIdentificationRequester;
3167
    }
3168

    
3169
    private int execute(VCSGisRequest request) {
3170
        while(true) {
3171
            switch(request.execute()) {
3172
                case ERR_CANT_AUTHENTICATE_USER:
3173
                case ERR_INVALID_AUTHENTICATION_TOKEN:
3174
                case ERR_USER_NOT_AUTHORIZED:
3175
                case ERR_AUTHENTICATION_EXPIRED:
3176
                case ERR_INVALID_USERCODE:
3177
                    if( this.userIdentificationRequester!= null ) {
3178
                        if( this.userIdentificationRequester.requestIdentification() ) {
3179
                            int r = this.authenticate(this.userIdentificationRequester.getUserId(), this.userIdentificationRequester.getPassword(), null);
3180
                            if(r == ERR_OK){
3181
                                request.setAuthenticationToken(this.authenticationToken);
3182
                                request.setUserCode(this.currentUserCode);
3183
                            }
3184
                            continue;
3185
                        }
3186
                    }
3187
                    // don't break
3188
                default:
3189
                    return request.getLastErrorCode();            
3190
            }
3191
        }
3192
    }
3193

    
3194

    
3195
    // TODO: eliminar la constante y contains para usar las de tools.
3196
    public static final Comparator<String> EQUALS_IGNORECASE_COMPARATOR = (Comparator<String>) (String o1, String o2) -> StringUtils.compareIgnoreCase(o1, o2);
3197
    public static boolean contains(Collection collection, Object value, Comparator comparator) {
3198
        for (Object item : collection) {
3199
            if( comparator.compare(item, value)==0 ) {
3200
                return true;
3201
            }
3202
        }
3203
        return false;
3204
    }
3205

    
3206
    @Override
3207
    public Collection<String> getEntityCategories() {
3208
        List<String> categories = new ArrayList<>();
3209
        if( this.hasRepositoryEntities() ) {
3210
            for (VCSGisEntity entity : this.getRepositoryEntities()) {
3211
                String category = entity.getCategory();
3212
                if( StringUtils.isNotBlank(category) ) {
3213
                    if( !contains(categories, category, EQUALS_IGNORECASE_COMPARATOR) ) {
3214
                        categories.add(category);
3215
                    }
3216
                }
3217
            }
3218
        }
3219
        for (VCSGisEntity entity : this.getWorkspaceEntities()) {
3220
            String category = entity.getCategory();
3221
            if( StringUtils.isNotBlank(category) ) {
3222
                if( !contains(categories, category, EQUALS_IGNORECASE_COMPARATOR) ) {
3223
                    categories.add(category);
3224
                }
3225
            }
3226
        }
3227
        Collections.sort(categories);
3228
        return Collections.unmodifiableCollection(categories);
3229
    }
3230
    
3231
    @Override
3232
    public String getTopologyPlan(String topologyPlanCode) {
3233
        if( StringUtils.isBlank(topologyPlanCode) ) {
3234
            return null;
3235
        }
3236
        TopologyplanTable topologyplanTable = new TopologyplanTable();
3237
        return topologyplanTable.getByCode(this, topologyPlanCode);
3238
    }
3239
    
3240
    @Override
3241
    public int importHistory(FeatureStore sourceStore,
3242
            String name,
3243
            String label,
3244
            String category,
3245
            String attrNameForLabel,
3246
            String fieldCodeName,
3247
            String fieldDateName,
3248
            String fieldOrderName) {
3249
        
3250
            I18nManager i18n = ToolsLocator.getI18nManager();
3251
            SimpleTaskStatus status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(i18n.getTranslation("_Import_history"));
3252
            status.setAutoremove(true);
3253
            status.add();
3254
            
3255
            FeatureStore target = null;
3256
            FeatureSet features = null;
3257
            
3258
        try{
3259
            VCSGisRepository repo = this.getRepository();
3260
            if (repo instanceof VCSGisRepositoryLocaldb){
3261
                ((VCSGisRepositoryLocaldb) repo).setAllowAssignTheRevisionDate(true);
3262
            }
3263
            
3264
            int result = this.addEntity(
3265
                    sourceStore.getDefaultFeatureTypeQuietly(),
3266
                    name, 
3267
                    null,
3268
                    attrNameForLabel, 
3269
                    category, 
3270
                    label,
3271
                    null
3272
            );
3273
            target = this.openFeatureStore(name);
3274
            FeatureQuery query = sourceStore.createFeatureQuery();
3275
            ExpressionBuilder expBuilder = ExpressionUtils.createExpressionBuilder();
3276
            query.getOrder().add(fieldDateName, true);
3277
            query.getOrder().add(fieldOrderName, true);
3278
            features = sourceStore.getFeatureSet(query);
3279
            target.edit(MODE_PASS_THROUGH);
3280
            Timestamp lastRevisionDate=null;
3281
            status.setRangeOfValues(0, features.size64());
3282
            status.setCurValue(0);
3283
            for (Feature sourceFeature : features) {
3284
                String filter = expBuilder.eq(expBuilder.column(fieldCodeName),
3285
                        expBuilder.constant(sourceFeature.get(fieldCodeName))
3286
                ).toString();
3287
                Feature targetFeature = target.findFirst(filter);
3288
                if (targetFeature == null) {
3289
                    if (lastRevisionDate==null){
3290
                        lastRevisionDate=sourceFeature.getTimestamp(fieldDateName);
3291
                    }
3292
                    if (Objects.equals(lastRevisionDate, sourceFeature.getTimestamp(fieldDateName))){
3293
                        EditableFeature editableTargetFeature = target.createNewFeature(sourceFeature);
3294
                        target.insert(editableTargetFeature);
3295
                    }else{
3296
                        result = this.commit(lastRevisionDate, lastRevisionDate, null, null);
3297
                        if (result!=ERR_OK){
3298
                            return result;
3299
                        }
3300
                        EditableFeature editableTargetFeature = target.createNewFeature(sourceFeature);
3301

    
3302
                        target.insert(editableTargetFeature);
3303
                        lastRevisionDate=sourceFeature.getTimestamp(fieldDateName);                       
3304
                    }
3305
                
3306
                }else{
3307
                    EditableFeature ef = targetFeature.getEditable();
3308
                    ef.copyFrom(sourceFeature);
3309
                    ef.setUpdatable(true);
3310
                    target.update(ef);
3311
                }
3312
                status.incrementCurrentValue();
3313
            }
3314
            result = this.commit(lastRevisionDate, lastRevisionDate, null, null);
3315
            if (result!=ERR_OK){
3316
                return result;
3317
            }
3318
            target.finishEditing();
3319
            status.terminate();
3320
            return ERR_OK;
3321
        }catch(Exception ex){
3322
            status.abort();
3323
            return -1;
3324
        }finally{
3325
            DisposeUtils.disposeQuietly(features);
3326
            DisposeUtils.disposeQuietly(target);
3327
        }
3328
    }
3329
    public int revert(String nameOrCode) {
3330
        return revert(nameOrCode, null);
3331
    }
3332
    
3333
    @Override
3334
    public int revert(String nameOrCode, SimpleTaskStatus status) {
3335
        if (status == null) {
3336
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Commit");
3337
            status.setAutoremove(true);
3338
            status.add();
3339
        }
3340

    
3341
//        FeatureStore entitiesStore = null;
3342

    
3343
        DataTransaction transaction = null;
3344
        try {
3345
            LOGGER.debug("===: REVERT " + this.getCode() + ", " + this.getLabel() + ", " + nameOrCode);
3346
            transaction = DALLocator.getDataManager().createTransaction();
3347
            transaction.begin();
3348
            
3349
            status.message("Reverting");
3350
            
3351
            EntityRow entity = this.getWorkspaceEntity(nameOrCode);
3352
            WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
3353
            FeatureStore userStore = null;
3354
            FeatureStore changesStore = null;
3355
//            String dataCodeFieldName = entity.getFeatureIdFieldName();
3356

    
3357
            DisposableFeatureSetIterable changes = changesTable.getSelectedsByEntityCodeAsIterator(this, entity.getEntityCode());
3358
            transaction.add(changes);
3359

    
3360

    
3361
            if (!changes.isEmpty()) {
3362
                userStore = this.openFeatureStore(entity);
3363
                transaction.add(userStore, true);
3364
                userStore.edit(MODE_PASS_THROUGH);
3365
                changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
3366
                transaction.add(changesStore, true);
3367
                changesStore.edit(MODE_PASS_THROUGH);
3368

    
3369
                status.setCurValue(0);
3370
                status.setRangeOfValues(0, changes.size64());
3371
                for (Feature feature : changes) {
3372
                    WorkspaceChangeRow change = new WorkspaceChangeRow(this, feature);
3373
                    change.revert(userStore, changesStore);
3374
//                    String data = change.getData();
3375
//                    JsonObject dataAsJson = change.getDataAsJson();
3376
//                    int operation = change.getOperation();
3377
//                    switch (change.getOperation()) {
3378
//                        case OP_ADD_ENTITY:
3379
//                            //TODO: remove entity ???
3380
////                            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
3381
////                            transaction.add(entitiesStore);
3382
////                            entitiesStore.edit(MODE_PASS_THROUGH);
3383
//                            break;
3384
//                        case OP_INSERT:
3385
//                            // Remove related feature
3386
//                            LOGGER.debug("===: REVERT: insert");
3387
//                            userStore.delete("\"" + dataCodeFieldName + "\"='" + change.getRelatedFeatureCode() + "'");
3388
//                            break;
3389
//                        case OP_UPDATE:
3390
//                            // Update related feature from old feature
3391
//                            Feature relatedFeature = change.getRelatedFeature();
3392
//                            EditableFeature ef = relatedFeature.getEditable();
3393
//                            ef.copyFrom(change.getDataAsJson());
3394
//                            userStore.update(ef);
3395
//                            break;
3396
//                        case OP_DELETE:
3397
//                            //Create new feature from old feature
3398
//                            JsonObject dataJson = change.getDataAsJson();
3399
//                            ef = userStore.createNewFeature(dataJson);
3400
//                            userStore.insert(ef);
3401
//                            break;
3402
//                    }
3403
                    status.incrementCurrentValue();
3404
                }
3405
                userStore.finishEditing();
3406
                changesStore.finishEditing();
3407
            }
3408
            
3409

    
3410
//            LOGGER.debug("===: REVERT: clean local changes");
3411
//            status.message("Removing local list of changes");
3412
//            changesTable.deleteSelectedsByEntity(this, entity.getEntityCode());
3413

    
3414
            status.message("Revert completed");
3415
            status.terminate();
3416
            return ERR_NO_ERROR;
3417
        } catch (Exception ex) {
3418
            LOGGER.warn("Can't revert changes.", ex);
3419
            status.message("Can't revert changes");
3420
            status.abort();
3421
            return ERR_CANT_REVERT;
3422
        } finally {
3423
            DisposeUtils.disposeQuietly(transaction);
3424
        }
3425
    }
3426
    
3427
    @Override
3428
    public int export(String entityName, String tableName, String revisionCode, Timestamp efectiveDate, SimpleTaskStatus status) {
3429
        FeatureStore target = null;
3430
        FeatureStore entitiesStore = null;
3431
        int errcode = ERR_OK;
3432
        VCSGisCheckoutRequest request = null;
3433
        if (status == null) {
3434
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("_Export");
3435
            status.setAutoremove(true);
3436
            status.add();
3437
        }
3438
        try {
3439
            LOGGER.debug("===: EXPORT " + this.getCode() + ", '" + this.getLabel() + "', " + tableName);
3440
            status.message("Preparing export");
3441
            VCSGisEntity lentity = this.getEntity(entityName);
3442
            if (lentity == null) {
3443
                status.message("Table " + tableName + " not exists");
3444
                status.abort();
3445
                return ERR_ENTITY_NOT_EXISTS;
3446
            }
3447
            reloadRepositoryEntities(status);
3448
            request = this.getRepository().createCheckoutRequest(entityName);
3449
            request.setAuthenticationToken(this.authenticationToken);
3450
            request.setUserCode(this.currentUserCode);
3451
            request.setEfectiveDate(efectiveDate);
3452
            request.setRevisionCode(revisionCode);
3453

    
3454
            status.message("Executing export request for " + tableName);
3455
            if ( execute(request) != ERR_OK) {
3456
                status.message("Can't export " + tableName + " (error " + request.getLastErrorCode() + ")");
3457
                status.abort();
3458
                return request.getLastErrorCode();
3459
            }
3460
            status.message("Updating " + tableName + " metadata");
3461
//            VCSGisEntity rentity = request.getEntity();
3462
//            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
3463
//            entitiesStore.edit(FeatureStore.MODE_FULLEDIT);
3464
//            VCSGisEntity rentity = request.getEntity();
3465
//            lentity = new EntityRow(this);
3466
//            rentity.copyto(lentity);
3467
//            lentity.insert(entitiesStore);
3468
//            LOGGER.debug("===: CHECKOUT " + this.getCode() + ", '" + this.getLabel() + "', " + tableName + ", rev." + rentity.getRepositoryRevisionCode());
3469

    
3470
//            this.forceReloadWorkspaceEntities();
3471
            status.message("Creating table " + tableName);
3472
            this.create_table(lentity, tableName);
3473

    
3474
            status.message("Adding features in " + tableName);
3475
            errcode = ERR_CANT_OPEN_STORE;
3476
            target = this.openFeatureStore(tableName);
3477
            this.addStoreIgnoreChanges(target);
3478
            DisposableIterable<VCSGisRepositoryData> data = request.getData();
3479
//            long sz = ContainerUtils.size64(data); // Con tablas tochas esto deja frita la app.
3480
//            status.setRangeOfValues(0, sz);
3481
            status.setCurValue(0);
3482
            errcode = ERR_CANT_INSERT_FEATURES;
3483
            target.edit(FeatureStore.MODE_APPEND);
3484
            for (VCSGisRepositoryData d : data) {
3485
                EditableFeature f = target.createNewFeature(d.getDataAsJson());
3486
                target.insert(f);
3487
                status.incrementCurrentValue();
3488
            }
3489
            target.finishEditing();
3490

    
3491
            status.message("Updating " + tableName + " metadata");
3492
//            if(StringUtils.isBlank(revisionCode)){
3493
//                lentity.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
3494
//            } else {
3495
//                lentity.setLocalRevisionCode(revisionCode);
3496
//            }
3497
//            lentity.update(entitiesStore);
3498
//            entitiesStore.finishEditing();
3499
//            this.forceReloadWorkspaceEntities();
3500
            request.dispose();
3501

    
3502
            status.message("Export completed");
3503
            status.terminate();
3504
            return ERR_NO_ERROR;
3505
        } catch (Exception ex) {
3506
            LOGGER.warn("Can't export.", ex);
3507
            status.message("Can't export");
3508
            status.abort();
3509
            if (target != null) {
3510
                target.cancelEditingQuietly();
3511
            }
3512
            if (entitiesStore != null) {
3513
                entitiesStore.cancelEditingQuietly();
3514
            }
3515
            return errcode;
3516
        } finally {
3517
            DisposeUtils.disposeQuietly(request);
3518
            if (target != null) {
3519
                this.removeStoreIgnoreChanges(target);
3520
            }
3521
            DisposeUtils.disposeQuietly(target);
3522
            DisposeUtils.disposeQuietly(entitiesStore);
3523

    
3524
        }
3525
    }
3526

    
3527
    @Override
3528
    public List<String> getDataModels() {
3529
        List<VCSGisEntity> rEntities = getRepositoryEntities();
3530
        Set<String> dataModels = new HashSet();
3531
        for (VCSGisEntity entity : rEntities) {
3532
            List<String> dataModelsEntity = entity.getDataModelsAsList();
3533
            dataModels.addAll(dataModelsEntity);
3534
        }
3535
        ArrayList<String> list = new ArrayList<>(dataModels);
3536
        Collections.sort(list);
3537
        return list;
3538
    }
3539
    
3540
    @Override
3541
    public void logout() {
3542
        VarsTable varsTable = new VarsTable();
3543
        varsTable.delete(this,"USER");
3544
        varsTable.delete(this,"AUTHENTICATIONTOKEN");
3545
        this.currentUserCode = null;
3546
        this.authenticationToken = null;
3547
    }
3548
}