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

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.VCSGisManagerImpl.INTERNAL_WORKSPACE_TABLES;
110
import org.gvsig.vcsgis.lib.VCSGisRevision;
111
import org.gvsig.vcsgis.lib.VCSGisRuntimeException;
112
import org.gvsig.vcsgis.lib.VCSGisTopologyPlan;
113
import org.gvsig.vcsgis.lib.VCSGisUser;
114
import org.gvsig.vcsgis.lib.VCSGisUserIdentificationRequester;
115
import org.gvsig.vcsgis.lib.VCSGisUtils;
116
import org.gvsig.vcsgis.lib.repository.VCSGisRepository;
117
import org.gvsig.vcsgis.lib.repository.VCSGisRepositoryChange;
118
import org.gvsig.vcsgis.lib.repository.VCSGisRepositoryData;
119
import org.gvsig.vcsgis.lib.repository.localdb.VCSGisRepositoryLocaldb;
120
import org.gvsig.vcsgis.lib.repository.localdb.tables.EntitiesRepoTable;
121
import org.gvsig.vcsgis.lib.repository.requests.VCSGisAuthenticateRequest;
122
import org.gvsig.vcsgis.lib.repository.requests.VCSGisCheckoutRequest;
123
import org.gvsig.vcsgis.lib.repository.requests.VCSGisCommitRequest;
124
import org.gvsig.vcsgis.lib.repository.requests.VCSGisEntitiesRequest;
125
import org.gvsig.vcsgis.lib.repository.requests.VCSGisHistoryRequest;
126
import org.gvsig.vcsgis.lib.repository.requests.VCSGisRequest;
127
import org.gvsig.vcsgis.lib.repository.requests.VCSGisTopologyPlansRequest;
128
import org.gvsig.vcsgis.lib.repository.requests.VCSGisUpdateRequest;
129
import org.gvsig.vcsgis.lib.repository.requests.VCSGisUsersRequest;
130
import org.gvsig.vcsgis.lib.workspace.tables.EntitiesTable;
131
import org.gvsig.vcsgis.lib.workspace.tables.EntitiesTable.EntityRow;
132
import org.gvsig.vcsgis.lib.workspace.tables.LocalRevisionsTable;
133
import org.gvsig.vcsgis.lib.workspace.tables.LocalRevisionsTable.LocalRevisionRow;
134
import org.gvsig.vcsgis.lib.workspace.tables.RemoteChangesTable;
135
import static org.gvsig.vcsgis.lib.workspace.tables.RemoteChangesTable.COD_ENTITY;
136
import org.gvsig.vcsgis.lib.workspace.tables.RemoteChangesTable.RemoteChangeRow;
137
import org.gvsig.vcsgis.lib.workspace.tables.TopologyplanTable;
138
import org.gvsig.vcsgis.lib.workspace.tables.UsersTable;
139
import org.gvsig.vcsgis.lib.workspace.tables.VarsTable;
140
import org.gvsig.vcsgis.lib.workspace.tables.WorkspaceChangesTable;
141
import org.gvsig.vcsgis.lib.workspace.tables.WorkspaceChangesTable.WorkspaceChangeRow;
142
import org.slf4j.Logger;
143
import org.slf4j.LoggerFactory;
144

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
492
    }
493

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

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

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

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

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

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

    
616
    @Override
617
    public OpenDataStoreParameters createOpenStoreParameters(String tableName) {
618
        try {
619
            JDBCStoreParameters params = this.wsexplorer.get(tableName);
620
            return params;
621
        } catch (Exception ex) {
622
            LOGGER.trace("can't create open store parameters from '" + this.getMessageLabel() + "'.", ex);
623
            return null;
624
        }
625
    }
626

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

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

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

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

    
691
                }
692

    
693
                return ERR_OK;
694
            }
695

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
854
            this.create_table(entity);
855

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

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

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

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

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

    
1008
    }
1009

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1188
            entity = this.getWorkspaceEntityByName(name);
1189

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

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

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

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

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

    
1228
            target.finishEditing();
1229

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

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

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

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

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

    
1262
            entitiesStore.edit(MODE_FULLEDIT);
1263

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

    
1267
            entitiesStore.finishEditing();
1268

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

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

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

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

    
1302
        };
1303
        return changes;
1304
    }
1305

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

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

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

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

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

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

    
1398
        };
1399
        return changes;
1400
    }
1401

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1789

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2073
            updateLocallyModyfiedRemoteChanges();
2074

    
2075
            transaction.commit();
2076

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

    
2090
    }
2091

    
2092
    private void updateLocallyModyfiedRemoteChanges() {
2093

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

    
2097
    }
2098

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

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

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

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

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

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

    
2229
    }
2230

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

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

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

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

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

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

    
2282
        EditableFeature ef;
2283
        DisposableFeatureSetIterable remoteChanges = null;
2284

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2481
            transaction.commit();
2482

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2988
    }
2989

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

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

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

    
3033
                doRemoveEntity(entity, transaction);
3034
            }
3035
            
3036
            forceReloadWorkspaceEntities();
3037
            transaction.commit();
3038
            return ERR_OK;
3039
        } catch (Exception ex) {
3040
            LOGGER.warn("Can't remove entity.", ex);
3041
            transaction.rollbackQuietly();
3042
            return err;
3043
        } finally {
3044
            transaction.dispose();
3045
        }
3046
        
3047
    }
3048

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

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

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

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

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

    
3193

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

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

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

    
3340
//        FeatureStore entitiesStore = null;
3341

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

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

    
3359

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

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

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

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

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

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

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

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

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

    
3523
        }
3524
    }
3525

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