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

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

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

    
149
    private static final Logger LOGGER = LoggerFactory.getLogger(VCSGisWorkspaceImpl.class);
150

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

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

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

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

    
214
    private String getProviderName() {
215
        return this.wsexplorer.getProviderName();
216
    }
217

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

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

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

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

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

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

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

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

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

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

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

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

    
355
    public ChangeListenerSupport getWorkspaceEntiesChangeListeners() {
356
        return this.workspaceEntitiesChangeListeners;
357
    }
358

    
359
    public ChangeListenerSupport getRepositoryEntiesChangeListeners() {
360
        return this.repositoryEntitiesChangeListeners;
361
    }
362

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
489
    }
490

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

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

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

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

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

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

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

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

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

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

    
677
                }
678

    
679
                return ERR_OK;
680
            }
681

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

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

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

    
731
                    case OP_DELETE:
732
                        return ERR_CANT_ADD_CHANGE;
733
                }
734
            }
735

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

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

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

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

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

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

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

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

    
825
            this.forceReloadWorkspaceEntities();
826
            err = ERR_CANT_INSERT_CHANGE;
827

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

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

    
840
            this.create_table(entity);
841

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

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

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

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

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

    
994
    }
995

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

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

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

    
1040
            this.addStoreIgnoreChanges(target);
1041
            entity = this.getWorkspaceEntityByName(name);
1042

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

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

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

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

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

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

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

    
1133
            target = (FeatureStore) dataManager.openStore(source.getProviderName(), source.getParameters());
1134

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

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

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

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

    
1171
            this.forceReloadWorkspaceEntities();
1172
            errcode = ERR_CANT_INSERT_CHANGE;
1173

    
1174
            entity = this.getWorkspaceEntityByName(name);
1175

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

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

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

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

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

    
1214
            target.finishEditing();
1215

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

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

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

    
1240
            target = (FeatureStore) dataManager.openStore(source.getProviderName(), source.getParameters());
1241

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

    
1248
            entitiesStore.edit(MODE_FULLEDIT);
1249

    
1250
            entity.setFeatureTypeAsJson(ft.toJsonBuilder().toString());
1251
            entity.update(entitiesStore);
1252

    
1253
            entitiesStore.finishEditing();
1254

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

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

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

    
1283
        };
1284
        return changes;
1285
    }
1286

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

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

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

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

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

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

    
1379
        };
1380
        return changes;
1381
    }
1382

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

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

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

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

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

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

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

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

    
1486
        VCSGisWorkspaceEntity localEntity = this.getWorkspaceEntity(entity);
1487
        request.add(request.createEntity(localEntity));
1488

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

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

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

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

    
1526
    @Override
1527
    public boolean canCommit() {
1528
        return canCommit(null);
1529
    }
1530

    
1531
    @Override
1532
    public boolean canCommit(MutableObject<String> message) {
1533

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

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

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

    
1569
    @Override
1570
    public List<VCSGisWorkspaceEntity> getEntitiesWithChanges() {
1571

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

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

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

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

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

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

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

    
1624
            boolean useSeleccion = this.prepareCommitRequest(request, revisiondate, efectivedate, comment, status);
1625

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

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

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

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

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

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

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

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

    
1757

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

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

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

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

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

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

    
1831
            status.message("Updating " + tableName + " metadata");
1832
            if(StringUtils.isBlank(revisionCode)){
1833
                lentity.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
1834
            } else {
1835
                lentity.setLocalRevisionCode(revisionCode);
1836
            }
1837
            lentity.update(entitiesStore);
1838
            entitiesStore.finishEditing();
1839
            this.forceReloadWorkspaceEntities();
1840
            
1841
            UsersTable usersTable = new UsersTable();
1842
            if( StringUtils.isNotBlank(request.getUsersHashCode()) ) {
1843
                if( StringUtils.equalsIgnoreCase(usersTable.getHashCode(this), request.getUsersHashCode())) {
1844
                    updateUsersFromRepository(status);
1845
                }
1846
            }
1847
            TopologyplanTable topologyPlansTable = new TopologyplanTable();
1848
            if( StringUtils.isNotBlank(request.getTopologyPlansHashCode()) ) {
1849
                if( StringUtils.equalsIgnoreCase(topologyPlansTable.getHashCode(this), request.getTopologyPlansHashCode())) {
1850
                    updateTopologyPlansFromRepository(status);
1851
                }
1852
            }
1853
            request.dispose();
1854

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

    
1873
        }
1874
    }
1875

    
1876
    private void updateUsersFromRepository(SimpleTaskStatus status) {
1877
        FeatureStore usersStore = null;
1878
        VCSGisUsersRequest request = null;
1879
        try {
1880
            request = this.getRepository().createUsersRequest();
1881
            request.setAuthenticationToken(this.authenticationToken);
1882
            request.setUserCode(this.currentUser);
1883

    
1884
            status.message("Executing users request");
1885
            if ( execute(request) != ERR_OK) {
1886
                status.message("Can't get users (error " + request.getLastErrorCode() + ")");
1887
                return;
1888
            }
1889
            status.message("Updating users information");
1890
            usersStore = this.openFeatureStore(UsersTable.TABLE_NAME);
1891
            usersStore.edit(FeatureStore.MODE_PASS_THROUGH);
1892
            usersStore.delete("TRUE");
1893
            for (VCSGisUser user : request.getUsers()) {
1894
                UsersTable.UserRow row = new UsersTable.UserRow(this);
1895
                row.copyFrom(user);
1896
                row.insert(usersStore);
1897
            }
1898
            usersStore.finishEditing();
1899
            
1900
        } catch(Exception ex) {
1901
            LOGGER.warn("Can't update users.", ex);
1902
            status.message("Can't update users");
1903
            FeatureStore.cancelEditingQuietly(usersStore);
1904
        } finally {
1905
            DisposeUtils.disposeQuietly(request);
1906
            DisposeUtils.disposeQuietly(usersStore);
1907
        }     
1908
    }
1909
    
1910
    private void updateTopologyPlansFromRepository(SimpleTaskStatus status) {
1911
        FeatureStore topologyPlanStore = null;
1912
        VCSGisTopologyPlansRequest request = null;
1913
        try {
1914
            request = this.getRepository().createTopologyPlansRequest();
1915
            request.setAuthenticationToken(this.authenticationToken);
1916
            request.setUserCode(this.currentUser);
1917

    
1918
            status.message("Executing topology plans request");
1919
            if ( execute(request) != ERR_OK) {
1920
                status.message("Can't get topology plans (error " + request.getLastErrorCode() + ")");
1921
                return;
1922
            }
1923
            status.message("Updating topology plans information");
1924
            topologyPlanStore = this.openFeatureStore(TopologyplanTable.TABLE_NAME);
1925
            topologyPlanStore.edit(FeatureStore.MODE_PASS_THROUGH);
1926
            topologyPlanStore.delete("TRUE");
1927
            for (VCSGisTopologyPlan topologyPlan : request.getTopologyPlans()) {
1928
                TopologyplanTable.TopologyPlanRow row = new TopologyplanTable.TopologyPlanRow(this);
1929
                row.copyFrom(topologyPlan);
1930
                row.insert(topologyPlanStore);
1931
            }
1932
            topologyPlanStore.finishEditing();
1933
            
1934
        } catch(Exception ex) {
1935
            LOGGER.warn("Can't update topology plans.", ex);
1936
            status.message("Can't update topology plans");
1937
            FeatureStore.cancelEditingQuietly(topologyPlanStore);
1938
        } finally {
1939
            DisposeUtils.disposeQuietly(request);
1940
            DisposeUtils.disposeQuietly(topologyPlanStore);
1941
        }     
1942
    }
1943
    
1944
    @Override
1945
    public int updateEntitiesFromRepository() {
1946
        return this.updateEntitiesFromRepository(null);
1947
    }
1948

    
1949
    @Override
1950
    public int updateEntitiesFromRepository(SimpleTaskStatus status) {
1951
        LOGGER.debug("===: UPDATE_ENTITIES " + this.getCode() + ", '" + this.getLabel() + "'");
1952
        FeatureStore entitiesStore = null;
1953
        EntitiesTable entitiesTable = new EntitiesTable();
1954
        if (status == null) {
1955
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Update metadata tables");
1956
            status.setAutoremove(true);
1957
            status.add();
1958
        }
1959
        try {
1960
            status.message("Preparing update metadata tables");
1961
            this.reloadRepositoryEntities(status);
1962

    
1963
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1964
            entitiesStore.edit(MODE_FULLEDIT);
1965
            for (VCSGisEntity rentity : this.getRepositoryEntities()) {
1966
                EntityRow entityRow = entitiesTable.getByEntityName(this, rentity.getEntityName());
1967
                if (entityRow != null) {
1968
                    rentity.copyto(entityRow);
1969
                    entityRow.update(entitiesStore);
1970
                }
1971
            }
1972
            entitiesStore.finishEditingQuietly();
1973

    
1974
            this.reloadWorkspaceEntities();
1975
            status.message("Update metadata tables completed");
1976
            status.terminate();
1977
            return ERR_OK;
1978
        } catch (Exception ex) {
1979
            LOGGER.warn("Can't update metadata tables.", ex);
1980
            status.message("Can't update metadata tables");
1981
            status.abort();
1982
            if (entitiesStore != null) {
1983
                entitiesStore.cancelEditingQuietly();
1984
            }
1985
            return ERR_CANT_UPDATE_ENTITIES;
1986
        } finally {
1987
            DisposeUtils.disposeQuietly(entitiesStore);
1988
            entitiesStore = null;
1989
        }
1990
    }
1991

    
1992
    @Override
1993
    public int updatePrepare(String tableName) {
1994
        return updatePrepare(tableName, null);
1995
    }
1996

    
1997
    @Override
1998
    public int updatePrepare(String tableName, SimpleTaskStatus status) {
1999
        LOGGER.debug("===: UPDATE_PREPARE: " + tableName + " WS " + this.getCode() + ", '" + this.getLabel() + "'");
2000
        if (status == null) {
2001
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Update-prepare " + tableName);
2002
            status.setAutoremove(true);
2003
            status.add();
2004
        }
2005

    
2006
        FeatureStore remoteChangesStore = null;
2007
        VCSGisUpdateRequest request = null;
2008
        DisposableIterable<VCSGisRepositoryData> remoteChanges = null;
2009
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
2010
        FeatureStore userStore = null;
2011
        FeatureStore localChangesStore = null;
2012
        FeatureStore entitiesStore = null;
2013
        DataTransaction transaction = null;
2014
        try {
2015
            transaction = DALLocator.getDataManager().createTransaction();
2016
            transaction.begin();
2017
            transaction.add(this.getExplorer(), false);
2018

    
2019
            status.message("Preparing update-prepare");
2020
            reloadRepositoryEntities(status);
2021
            request = this.getRepository().createUpdateRequest(tableName);
2022
            transaction.add(request);
2023
            request.setAuthenticationToken(this.authenticationToken);
2024
            request.setUserCode(this.currentUser);
2025
            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
2026
            if (lentity != null) {
2027
                request.setLocalRevisionCode(lentity.getLocalRevisionCode());
2028
            }
2029
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
2030
            transaction.add(entitiesStore);
2031
            status.message("Executing update-prepare request");
2032
            if ( execute(request) != ERR_OK) {
2033
                status.message("Can't update-prepare " + tableName + " (error " + request.getLastErrorCode() + ")");
2034
                status.abort();
2035
                return request.getLastErrorCode();
2036
            }
2037
            entitiesStore.edit(MODE_FULLEDIT);
2038
            status.message("Updating " + tableName + " metadata");
2039
            LOGGER.debug("===: UPDATE_PREPARE: " + tableName + " request code " + request.getCode());
2040
            VCSGisEntity rentity = request.getEntity();
2041
            if (lentity == null) {
2042
                lentity = new EntityRow(this);
2043
                lentity.copyfrom(rentity);
2044
                lentity.setLocalRevisionCode(null);
2045
                lentity.insert(entitiesStore);
2046
            } else {
2047
                lentity.copyfrom(rentity);
2048
                lentity.update(entitiesStore);
2049
            }
2050
//            this.reloadWorkspaceEntities();
2051
            String entityCode = lentity.getCode();
2052
            LOGGER.debug("===: UPDATE_PREPARE: " + tableName + " entity code " + entityCode + ", repo rev. " + lentity.getRepositoryRevisionCode() + ", local rev. " + lentity.getLocalRevisionCode());
2053

    
2054
            status.message("Preparing remote changes container");
2055
            remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
2056
            transaction.add(remoteChangesStore);
2057
            remoteChangesStore.edit(MODE_PASS_THROUGH);
2058

    
2059
            status.message("Deleting previous temporary remote changes");
2060
            LOGGER.debug("===: UPDATE_PREPARE: Delete updates table");
2061
            remoteChangesStore.delete("\"" + COD_ENTITY + "\"='" + entityCode + "'");
2062

    
2063
            remoteChanges = request.getData();
2064
            transaction.add(remoteChanges);
2065
//            long sz = ContainerUtils.size64(remoteChanges);
2066
//            status.setRangeOfValues(0, sz);
2067
            status.setCurValue(0);
2068

    
2069
            LOGGER.debug("===: UPDATE_PREPARE: Inserting updates");
2070
            userStore = this.openFeatureStore(lentity);
2071
            localChangesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
2072
            transaction.add(userStore);
2073
            transaction.add(localChangesStore);
2074
            localChangesStore.edit(MODE_PASS_THROUGH);
2075
            status.message("Downloading list of remote changes");
2076
            for (VCSGisRepositoryData remoteChange : remoteChanges) {
2077
                RemoteChangeRow remoteChangeRow = new RemoteChangeRow(this);
2078
//                LOGGER.debug("===: UPDATE_PREPARE: insert "+remoteChange.getFeatureRelatedCode()+", "+remoteChange.getOperation()+", "+remoteChange.getData());
2079
//                remoteChangeRow.setCode(remoteChange.getFeatureRelatedCode());
2080
                remoteChangeRow.newCode();
2081
                remoteChangeRow.setData(remoteChange.getData());
2082
                remoteChangeRow.setEntityCode(remoteChange.getEntityCode());
2083
                remoteChangeRow.setDataCode(remoteChange.getFeatureRelatedCode());
2084
                remoteChangeRow.setOperation(remoteChange.getOperation());
2085
                remoteChangeRow.setRevisionCode(remoteChange.getRevisionCode());
2086
                remoteChangeRow.setRevisionNumber(remoteChange.getRevisionNumber());
2087
                switch (remoteChange.getOperation()) {
2088
                    case OP_INSERT:
2089
                        remoteChangeRow.setStatus(STATE_LOCAL_NEW);
2090
                        break;
2091
                    case OP_UPDATE:
2092
                    case OP_DELETE:
2093
                        remoteChangeRow.setStatus(STATE_LOCAL_OUTDATED);
2094
                        break;
2095
                    default:
2096
                        remoteChangeRow.setStatus(STATE_LOCAL_UNMODIFIED);
2097
                        break;
2098
                }
2099

    
2100
                if (hasConflictRemoteChangeWithUserTable(lentity, remoteChange, userStore)) {
2101
                    remoteChangeRow.setStatus(STATE_CONFLICT);
2102
                    lentity.setState(STATE_CONFLICT);
2103
                }
2104

    
2105
                LOGGER.debug("===: UPDATE_PREPARE: row code = " + remoteChangeRow.getRelatedFeatureCode());
2106
                LOGGER.debug("===: UPDATE_PREPARE: row state = " + lentity.getState() + ", " + lentity.getStateLabel());
2107
                LOGGER.debug("===: UPDATE_PREPARE: row operation = " + remoteChangeRow.getOperation() + ", " + remoteChangeRow.getOperationLabel());
2108
                switch (lentity.getState()) {
2109
                    case STATE_LOCAL_OUTDATED:
2110
                    case STATE_LOCAL_UNMODIFIED:
2111
                        remoteChangeRow.setSelected(true);
2112
                        break;
2113
                    case STATE_CONFLICT:
2114
                        remoteChangeRow.setSelected(false);
2115
                        DisposableIterable<WorkspaceChangeRow> localChanges = changesTable.getChangesWidthUserData(this, lentity, remoteChangeRow, localChangesStore);
2116
                        if (localChanges != null) {
2117
                            for (WorkspaceChangeRow localChange : localChanges) {
2118
                                localChange.setStatus(STATE_CONFLICT);
2119
                                localChange.update(localChangesStore);
2120
                            }
2121
                            localChanges.dispose();
2122
                        }
2123
                    // Don't break to continue run next cases
2124
                    case STATE_LOCAL_NEW:
2125
                    case STATE_LOCAL_OUTDATED_AND_MODIFIED:
2126
                    case STATE_LOCAL_MODIFIED:
2127
                        WorkspaceChangeRow localChange = changesTable.getByEntityAndDataCode(this,
2128
                                entityCode,
2129
                                remoteChangeRow.getRelatedFeatureCode(),
2130
                                localChangesStore
2131
                        );
2132
                        if (localChange == null) {
2133
                            LOGGER.debug("===: UPDATE_PREPARE: no local modificacion, update local data");
2134
                            // Solo actualizamos si no ha sido modificado localmente y el cambio remoto no tiene conflictos
2135
                            if (remoteChangeRow.getStatus() != STATE_CONFLICT) {
2136
                                remoteChangeRow.setSelected(true);
2137
                            }
2138
                        } else {
2139
                            LOGGER.debug("===: UPDATE_PREPARE: not update. Local data is modified. " + localChange.getRelatedFeatureData().replace('\n', ' '));
2140
                            remoteChangeRow.setSelected(false);
2141
                            if (localChange.getStatus() != STATE_CONFLICT) {
2142
                                localChange.setStatus(STATE_LOCAL_OUTDATED_AND_MODIFIED);
2143
                                localChange.update(localChangesStore);
2144
                            }
2145
                        }
2146
                        break;
2147

    
2148
                }
2149
                remoteChangeRow.insert(remoteChangesStore);
2150
                status.incrementCurrentValue();
2151
            }
2152
            LOGGER.debug("===: UPDATE_PREPARE: finish inserting updates");
2153
            lentity.update(entitiesStore);
2154

    
2155
            remoteChangesStore.finishEditing();
2156
            localChangesStore.finishEditing();
2157
            entitiesStore.finishEditing();
2158

    
2159
            updateLocallyModyfiedRemoteChanges();
2160

    
2161
            transaction.commit();
2162

    
2163
            status.message("Update-prepare completed");
2164
            status.terminate();
2165
            return ERR_OK;
2166
        } catch (Exception ex) {
2167
            LOGGER.warn("Can't prepare update.", ex);
2168
            status.message("Can't prepare update");
2169
            status.abort();
2170
            DataTransaction.rollbackQuietly(transaction);
2171
            return ERR_CANT_PREPARE_UPDATE;
2172
        } finally {
2173
            DisposeUtils.disposeQuietly(transaction);
2174
        }
2175

    
2176
    }
2177

    
2178
    private void updateLocallyModyfiedRemoteChanges() {
2179

    
2180
        RemoteChangesTable changes = new RemoteChangesTable();
2181
        changes.updateStateFromLocalChanges(this, STATE_LOCAL_OUTDATED_AND_MODIFIED);
2182

    
2183
    }
2184

    
2185
    private boolean hasConflictRemoteChangeWithUserTable(VCSGisEntity lentity, VCSGisRepositoryData remoteChange, FeatureStore store) throws DataException {
2186
        if (store != null) {
2187
            FeatureType featType = lentity.getFeatureType();
2188
            JsonObject data = remoteChange.getDataAsJson();
2189
            ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
2190
            ExpressionBuilder builder = expManager.createExpressionBuilder();
2191
            builder.set(null);
2192
            for (FeatureAttributeDescriptor attr : featType) {
2193
                if (attr.isIndexed() && !attr.allowIndexDuplicateds()) {
2194
                    Object value = Json.toObject(data, attr.getName());
2195
                    builder.and(
2196
                            builder.eq(
2197
                                    builder.column(attr.getName()),
2198
                                    builder.constant(value)
2199
                            )
2200
                    );
2201

    
2202
                    Feature f = store.findFirst(builder.toString());
2203
                    if (f != null && !StringUtils.equals(
2204
                            f.getString(lentity.getFeatureIdFieldName()),
2205
                            remoteChange.getFeatureRelatedCode())) {
2206
                        return true;
2207
                    }
2208
                }
2209
            }
2210
        }
2211
        return false;
2212
    }
2213

    
2214
//    private Feature getUserFeatureConflictWithRemoteChange(VCSGisEntity lentity, RemoteChangeRow remoteChange, FeatureStore store) throws DataException {
2215
//        if(store != null) {
2216
//            FeatureType featType = lentity.getFeatureType();
2217
//            JsonObject data = remoteChange.getDataAsJson();
2218
//            ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
2219
//            ExpressionBuilder builder = expManager.createExpressionBuilder();
2220
//            builder.set(null);
2221
//            for (FeatureAttributeDescriptor attr : featType) {
2222
//                if(attr.isIndexed() && !attr.allowIndexDuplicateds()){
2223
//                    Object value = Json.toObject(data, attr.getName());
2224
//                    builder.and(
2225
//                        builder.eq(
2226
//                            builder.column(attr.getName()), 
2227
//                            builder.constant(value)
2228
//                        )
2229
//                    );
2230
//                    Feature targetFeature = store.findFirst(builder.toString());
2231
//                    if(targetFeature != null && !StringUtils.equals(
2232
//                            targetFeature.getString(lentity.getFeatureIdFieldName()),
2233
//                            remoteChange.getRelatedFeatureCode())
2234
//                        ){
2235
//                        return targetFeature;
2236
//                    }
2237
//                }
2238
//            }
2239
//        }
2240
//        return null;
2241
//    }
2242
    private DisposableFeatureSetIterable getUserFeaturesConflictWithRemoteChange(VCSGisEntity lentity, RemoteChangeRow remoteChange, FeatureStore store) throws DataException {
2243
        if (store == null) {
2244
            return null;
2245
        }
2246
        FeatureType featType = lentity.getFeatureType();
2247
        JsonObject data = remoteChange.getRelatedFeatureDataAsJson();
2248
        ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
2249
        ExpressionBuilder builder = expManager.createExpressionBuilder();
2250
        builder.set(null);
2251
        for (FeatureAttributeDescriptor attr : featType) {
2252
            if (StringUtils.equalsAnyIgnoreCase(lentity.getFeatureIdFieldName(), attr.getName())) {
2253
                continue;
2254
            }
2255
            if (attr.isIndexed() && !attr.allowIndexDuplicateds()) {
2256
                Object value = Json.toObject(data, attr.getName());
2257
                builder.or(
2258
                        builder.eq(
2259
                                builder.column(attr.getName()),
2260
                                builder.constant(value)
2261
                        )
2262
                );
2263
            }
2264
        }
2265
        ExpressionBuilder.Value value = builder.value();
2266
        if (value == null) {
2267
            return null;
2268
        }
2269
        ExpressionBuilder.BinaryOperator filter = builder.and(
2270
                builder.not(
2271
                        builder.eq(
2272
                                builder.column(lentity.getFeatureIdFieldName()),
2273
                                builder.constant(remoteChange.getRelatedFeatureCode())
2274
                        )
2275
                ),
2276
                value
2277
        );
2278

    
2279
        FeatureSet feats = store.getFeatureSet(filter.toString());
2280
        return feats.iterable();
2281
    }
2282

    
2283
    @Override
2284
    public int updateClean(String entityCode) {
2285
        return updateClean(entityCode, null);
2286
    }
2287

    
2288
    @Override
2289
    public int updateClean(String entityCode, SimpleTaskStatus status) {
2290
        VCSGisEntity entity = this.getEntity(entityCode);
2291
        if (entity == null) {
2292
            return ERR_ENTITY_NOT_EXISTS;
2293
        }
2294
        if (status == null) {
2295
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2296
                    "Update-clean " + entity.getEntityName()
2297
            );
2298
            status.setAutoremove(true);
2299
            status.add();
2300
        }
2301
        try {
2302
            status.message("Deleting temporary remote changes (" + entity.getEntityName() + ")");
2303
            RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2304
            remoteChangesTable.delete(this, entityCode);
2305
            status.message("Delete temporary remote changes completed");
2306
            status.terminate();
2307
            return ERR_OK;
2308
        } catch (Exception ex) {
2309
            LOGGER.warn("Can't deleting temporary remote changes of " + entity.getEntityName() + ".", ex);
2310
            status.message("Can't deleting temporary remote changes of " + entity.getEntityName() + ".");
2311
            status.abort();
2312
            return ERR_CANT_UPDATE_CLEAN;
2313
        }
2314

    
2315
    }
2316

    
2317
    @Override
2318
    public int update(String tableName) {
2319
        return this.update(tableName, false, false, null);
2320
    }
2321

    
2322
    @Override
2323
    public int update(String tableName, SimpleTaskStatus status) {
2324
        return this.update(tableName, false, false, status);
2325
    }
2326

    
2327
    @Override
2328
    public int merge(String tableName) {
2329
        return this.update(tableName, false, true, null);
2330
    }
2331

    
2332
    @Override
2333
    public int merge(String tableName, SimpleTaskStatus status) {
2334
        return this.update(tableName, false, true, status);
2335
    }
2336

    
2337
    public int update(String tableName, boolean prepare, boolean merge, SimpleTaskStatus status) {
2338
        int errcode = ERR_NO_ERROR;
2339
        if (status == null) {
2340
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2341
                    "Update " + tableName
2342
            );
2343
            status.setAutoremove(true);
2344
            status.add();
2345
        }
2346
        if (prepare) {
2347
            errcode = this.updatePrepare(tableName, status);
2348
            if (errcode != ERR_OK) {
2349
                return errcode;
2350
            }
2351
        }
2352
        LOGGER.debug("===: UPDATE " + this.getCode() + ", '" + this.getLabel() + "', " + tableName);
2353
        RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2354
        WorkspaceChangesTable localChangesTable = new WorkspaceChangesTable();
2355

    
2356
        EditableFeature ef;
2357
        DisposableFeatureSetIterable remoteChanges = null;
2358

    
2359
        FeatureStore workspaceChangesStore = null;
2360
        FeatureStore remoteChangesStore = null;
2361
        FeatureStore userStore = null;
2362
        FeatureStore entitiesStore = null;
2363

    
2364
        DataTransaction transaction = null;
2365
        try {
2366
            transaction = DALLocator.getDataManager().createTransaction();
2367
            transaction.begin();
2368

    
2369
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
2370
            transaction.add(entitiesStore);
2371
            entitiesStore.edit(MODE_PASS_THROUGH);
2372

    
2373
            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
2374
            if (lentity == null) {
2375
                lentity = new EntityRow(this);
2376
                VCSGisEntity rentity = this.getRepositoryEntityByName(tableName);
2377
                lentity.copyfrom(rentity);
2378
                lentity.setLocalRevisionCode(null);
2379
                lentity.update(entitiesStore);
2380
            }
2381
            if (!merge) {
2382
                status.message("Checking the need to merge");
2383
                if (remoteChangesTable.updateNeedMerge(this, lentity.getEntityCode())) {
2384
                    status.message("Can't update without merge.");
2385
                    status.abort();
2386
                    return ERR_UPDATE_NEED_MERGE;
2387
                }
2388
            }
2389
            String dataCodeFieldName = lentity.getFeatureIdFieldName();
2390
            status.message("Searching remote changes (" + lentity.getEntityName() + ")");
2391

    
2392
            userStore = this.openFeatureStore(lentity);
2393
            if (userStore == null) {
2394
                this.create_table(lentity);
2395
                userStore = this.openFeatureStore(lentity);
2396
            }
2397
            transaction.add(userStore);
2398
            userStore.edit(MODE_PASS_THROUGH);
2399

    
2400
            workspaceChangesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
2401
            transaction.add(workspaceChangesStore);
2402
            workspaceChangesStore.edit(MODE_PASS_THROUGH);
2403

    
2404
            remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
2405
            transaction.add(remoteChangesStore);
2406
            remoteChangesStore.edit(MODE_PASS_THROUGH);
2407

    
2408
            remoteChanges = remoteChangesTable.getSelectedsByEntityCodeAsIterator(this, lentity.getCode());
2409
            transaction.add(remoteChanges);
2410
//            long sz = ContainerUtils.size64(remoteChanges);
2411
//            status.setRangeOfValues(0, sz);
2412
            status.setCurValue(0);
2413

    
2414
            if (!remoteChanges.isEmpty()) {
2415
                this.addStoreIgnoreChanges(userStore);
2416
                status.message("Updating table (" + lentity.getEntityName() + ")");
2417
                FeatureType type = userStore.getDefaultFeatureTypeQuietly();
2418

    
2419
                ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
2420
                ExpressionBuilder builder = expManager.createExpressionBuilder();
2421

    
2422
                for (Feature feature : remoteChanges) {
2423
                    RemoteChangeRow remoteChangeRow = new RemoteChangeRow(this, feature);
2424
                    switch (remoteChangeRow.getOperation()) {
2425
                        case OP_INSERT:
2426
                            LOGGER.debug("===: UPDATE: insert");
2427
                            switch (remoteChangeRow.getStatus()) {
2428
                                case STATE_CONFLICT:
2429
                                    DisposableFeatureSetIterable feats = getUserFeaturesConflictWithRemoteChange(lentity, remoteChangeRow, userStore);
2430
                                    if (feats != null) {
2431
                                        List<Feature> featuresToDelete = new ArrayList<Feature>();
2432
                                        for (Feature feat : feats) {
2433
                                            if (feat != null) {
2434
//                                                userStore.delete(feat);
2435
                                                featuresToDelete.add(feat);
2436
                                                workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\" = '" + feat.getString(lentity.getFeatureIdFieldName()) + "'");
2437
                                            }
2438
                                        }
2439
                                        for (Feature feat : featuresToDelete) {
2440
                                            userStore.delete(feat);
2441
                                        }
2442
                                        DisposeUtils.disposeQuietly(feats);
2443
                                    }
2444
                                //Don't break to do the default case
2445
                                default:
2446
                                    ef = userStore.createNewFeature(remoteChangeRow.getRelatedFeatureDataAsJson());
2447
                                    userStore.insert(ef);
2448
                                    break;
2449
                            }
2450
                            break;
2451
                        case OP_UPDATE:
2452
                            LOGGER.debug("===: UPDATE: update");
2453
                            JsonObject dataJson = remoteChangeRow.getRelatedFeatureDataAsJson();
2454
                            builder.set(null);
2455
                            for (FeatureAttributeDescriptor attr : type.getPrimaryKey()) {
2456
                                builder.and(
2457
                                        builder.eq(
2458
                                                builder.column(attr.getName()),
2459
                                                builder.constant(
2460
                                                        Json.toObject(dataJson.get(attr.getName()))
2461
                                                )
2462
                                        )
2463
                                );
2464
                            }
2465
                            Feature f = userStore.findFirst(builder.toString());
2466
                            if (f == null) {
2467
                                WorkspaceChangeRow localChange = localChangesTable.find(this, workspaceChangesStore, lentity.getEntityCode(), remoteChangeRow.getRelatedFeatureCode());
2468
                                if(localChange != null && localChange.getOperation() == OP_DELETE){
2469
                                    ef = userStore.createNewFeature(remoteChangeRow.getRelatedFeatureDataAsJson());
2470
                                    userStore.insert(ef);
2471
                                    break;
2472
                                } else {
2473
                                    throw new NullPointerException("Can't update null feature (" + builder.toString() + ").");
2474
                                }
2475
                            }
2476
                            ef = f.getEditable();
2477
                            ef.copyFrom(dataJson);
2478
                            userStore.update(ef);
2479
//                            workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\"='" + remoteChangeRow.getRelatedFeatureCode()+ "'");
2480
                            break;
2481

    
2482
                        case OP_DELETE:
2483
                            LOGGER.debug("===: UPDATE: delete");
2484
                            userStore.delete("\"" + dataCodeFieldName + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2485
//                            workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\"='" + remoteChangeRow.getRelatedFeatureCode()+ "'");
2486
                            break;
2487
                    }
2488
                    status.incrementCurrentValue();
2489
                }
2490
            }
2491

    
2492
            if (merge) {
2493
                status.message("Searching local changes to merge (" + lentity.getEntityName() + ")");
2494
                DisposeUtils.disposeQuietly(remoteChanges);
2495
                remoteChanges = remoteChangesTable.getNotSelectedsByEntityCodeAsIterator(this, lentity.getCode());
2496
                transaction.add(remoteChanges);
2497
//                sz = ContainerUtils.size64(remoteChanges);
2498
//                status.setRangeOfValues(0, sz);
2499
                status.setCurValue(0);
2500

    
2501
                if (!remoteChanges.isEmpty()) {
2502
                    //We edit the changesStore because we will need local changes 
2503
//                    workspaceChangesStore.edit(MODE_PASS_THROUGH);
2504

    
2505
                    //We edit the destination store because we may need to update some features (in case OP_DELETE)
2506
//                    userStore.edit(MODE_PASS_THROUGH);
2507
                    this.addStoreIgnoreChanges(userStore);
2508

    
2509
                    status.message("Adding to local changes (" + lentity.getEntityName() + ")");
2510
                    for (Feature feature : remoteChanges) {
2511
                        RemoteChangeRow remoteChangeRow = new RemoteChangeRow(this, feature);
2512
                        Feature f = userStore.findFirst("\"" + lentity.getFeatureIdFieldName() + "\" = '" + remoteChangeRow.getRelatedFeatureCode() + "'");
2513
                        switch (remoteChangeRow.getOperation()) {
2514
                            case OP_INSERT:
2515
                                LOGGER.debug("===: UPDATE: insert");
2516
                                if (f == null) {
2517
                                    this.addDeleteChange(lentity, workspaceChangesStore, remoteChangeRow.getRelatedFeatureCode(), null, null);
2518
                                } else {
2519
                                    this.addChange(lentity, OP_UPDATE, workspaceChangesStore, f, null);
2520
                                }
2521
                                break;
2522

    
2523
                            case OP_UPDATE:
2524
                                LOGGER.debug("===: UPDATE: update");
2525
                                if (f == null) {
2526
                                    this.addDeleteChange(lentity, workspaceChangesStore, remoteChangeRow.getRelatedFeatureCode(), null, null);
2527
                                } else {
2528
                                    this.addChange(lentity, OP_UPDATE, workspaceChangesStore, f, null);
2529
                                }
2530
                                break;
2531
                            case OP_DELETE:
2532
                                LOGGER.debug("===: UPDATE: delete");
2533
                                if (f != null) {
2534
                                    userStore.delete("\"" + dataCodeFieldName + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2535

    
2536
                                    ef = userStore.createNewFeature(f);
2537
                                    ef.setString(lentity.getFeatureIdFieldName(), this.createUniqueCode());
2538
                                    userStore.insert(ef);
2539

    
2540
                                    workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2541
                                    this.addChange(lentity, OP_INSERT, workspaceChangesStore, ef, null);
2542

    
2543
                                }
2544
                                break;
2545
                        }
2546
                        status.incrementCurrentValue();
2547
                    }
2548
                }
2549
            }
2550
            localChangesTable.removeLocalChangesRelatedToSelectedRemoteChanges(this, lentity);
2551
            remoteChangesTable.delete(remoteChangesStore, lentity.getEntityCode());
2552

    
2553
            status.message("Updating metadata tables");
2554
            lentity.setLocalRevisionCode(lentity.getRepositoryRevisionCode());
2555
            lentity.update(entitiesStore);
2556
            forceReloadWorkspaceEntities();
2557

    
2558
            transaction.commit();
2559

    
2560
            status.message("Update completed");
2561
            status.terminate();
2562
            return ERR_OK;
2563
        } catch (Exception ex) {
2564
            LOGGER.warn("Can't update.", ex);
2565
            status.message("Can't update");
2566
            status.abort();
2567
            return ERR_CANT_UPDATE;
2568
        } finally {
2569
            this.removeStoreIgnoreChanges(userStore);
2570
            DisposeUtils.disposeQuietly(transaction);
2571
        }
2572
    }
2573

    
2574
    @Override
2575
    public JDBCServerExplorer getExplorer() {
2576
        return this.wsexplorer;
2577
    }
2578

    
2579
//    @Override
2580
//    public int log(String tableName, int maxRevisions, int operation, SimpleTaskStatus status){
2581
//        
2582
//        
2583
//        FeatureStore localRevisionsStore = null;
2584
//        int errcode = ERR_OK;
2585
//        VCSGisLogRequest request = null;
2586
//        if( status==null ) {
2587
//            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2588
//                    "Log "+tableName
2589
//            );
2590
//            status.setAutoremove(true);
2591
//            status.add();
2592
//        }
2593
//        try {
2594
//            LOGGER.debug("===: LOG "+this.getCode()+", '"+this.getLabel()+"', "+tableName);
2595
//            reloadRepositoryEntities(status);
2596
//
2597
//            //TODO calcular las revisiones que tengo para excluirlas
2598
//            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
2599
//            if(lentity == null){
2600
//                status.message("Can't find table '"+tableName+"'");
2601
//                status.abort();
2602
//                return ERR_ENTITY_NOT_EXISTS;
2603
//            }
2604
//            
2605
//            
2606
//            LocalRevisionsTable localRevisionsTable = new LocalRevisionsTable();
2607
//            GetItemWithSizeAndIterator64<Feature> lrevisions = localRevisionsTable.getAllRevisions(this, lentity.getEntityCode());
2608
//            //Asumimos que lrevisions esta ordenado ascendentemente por numero de revision
2609
////            Long prevRevNumber = null;
2610
//            Long minRevision = null;
2611
//            Long maxRevision = null;
2612
//            for (Feature lrevision : lrevisions) {
2613
//                LocalRevisionRow x = new LocalRevisionRow(this, lrevision);
2614
//                Long revNumber = x.getNumber();
2615
//                //Asumimos que las revisiones que tenemos son consecutivas
2616
////                if(prevRevNumber != null && revNumber != prevRevNumber+1){ //Salto
2617
//                    //Borrar la tabla completamente ???
2618
////                    target = this.getFeatureStore(LocalRevisionsTable.TABLE_NAME);
2619
////                    target.edit(MODE_PASS_THROUGH);
2620
////                    target.delete
2621
////                }
2622
//                if(minRevision == null){
2623
//                    minRevision = revNumber;
2624
//                }
2625
//                maxRevision = revNumber;
2626
//            }
2627
//            
2628
//            status.message("Executing log request");
2629
//            request = this.getRepository().createLogRequest(tableName);
2630
//            if(minRevision != null && maxRevision != null){
2631
//                request.setExcludeRevisionsRange(Range.between(minRevision, maxRevision));
2632
//            }
2633
//            request.setOperation(operation);
2634
//            request.setMaxRevisions(maxRevisions);
2635
//            
2636
//            if( request.execute()!=ERR_OK ) {
2637
//                status.message("Can't retriev history of "+tableName+" (error "+request.getLastErrorCode()+")");
2638
//                status.abort();
2639
//                return request.getLastErrorCode();
2640
//            }
2641
//
2642
//            status.message("Deleting previous local revision information");
2643
//            errcode = ERR_CANT_OPEN_STORE;
2644
//            localRevisionsStore = this.openFeatureStore(LocalRevisionsTable.TABLE_NAME);
2645
//            errcode = ERR_CANT_RETRIEVE_SOURCE_FEATURES;
2646
//            DisposableIterable<VCSGisRevision> revisions = request.getRevisions();
2647
//            status.message("Adding to local revisions");
2648
//            long sz = ContainerUtils.size64(revisions);
2649
//            status.setRangeOfValues(0, sz);
2650
//            status.setCurValue(0);
2651
//            
2652
//            errcode = ERR_CANT_INSERT_FEATURES;
2653
//            localRevisionsStore.edit(FeatureStore.MODE_PASS_THROUGH);
2654
//            for (VCSGisRevision revision : revisions) {
2655
//                if(operation == VCSGisLogRequest.LOG_OP_LAST && revision.getNumber()!=maxRevision+1){
2656
//                    //Borrar todo el target ???
2657
//                }
2658
//                EditableFeature targetFeature = localRevisionsStore.createNewFeature();
2659
//                LocalRevisionRow row = new LocalRevisionRow(this, targetFeature);
2660
//                row.copyFrom(revision);
2661
//                row.insert(localRevisionsStore);
2662
//                status.incrementCurrentValue();
2663
//            }
2664
//            localRevisionsStore.finishEditing();
2665
//            status.message("Log completed");
2666
//            status.terminate();
2667
//            return ERR_OK;
2668
//        } catch (Exception ex) {
2669
//            LOGGER.warn("Can't retrieve history.", ex);
2670
//            FeatureStore.cancelEditingQuietly(localRevisionsStore);
2671
//            status.message("Can't retrieve history");
2672
//            status.abort();
2673
//            return errcode;
2674
//        } finally {
2675
//            DisposeUtils.disposeQuietly(request);
2676
//            if(localRevisionsStore != null) {
2677
//                this.removeStoreIgnoreChanges(localRevisionsStore);
2678
//            }
2679
//            DisposeUtils.disposeQuietly(localRevisionsStore);
2680
//        }
2681
//    }
2682
//
2683
//    @Override
2684
//    public List<VCSGisWorkspaceRevision> getRemoteRevisions(String tableName) {
2685
////        LocalRevisionsTable table = new LocalRevisionsTable();
2686
////        features = table.getAllRevisions(this, tableName);
2687
//        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
2688
//    }
2689
    @Override
2690
    public void reloadRepositoryEntities(SimpleTaskStatus status) {
2691
        boolean isMyStatus = false;
2692
        if (status == null) {
2693
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Repository tables");
2694
            status.setAutoremove(true);
2695
            status.add();
2696
            status.push();
2697
            isMyStatus = true;
2698
        }
2699
        FeatureStore store = null;
2700
        FeatureSet fset = null;
2701
        try {
2702
            status.message("Getting repository table metadata");
2703
            VCSGisEntitiesRequest request = this.getRepository().createEntitiesRequest();
2704
            request.setAuthenticationToken(this.authenticationToken);
2705
            request.setUserCode(this.currentUser);
2706
            if ( execute(request) != ERR_OK) {
2707
                throw new VCSGisRuntimeException(request.getLastErrorCode(), request.getLastErrorMessage());
2708
            }
2709
            List<VCSGisEntity> entities = request.getRepositoryEntities();
2710
            request.dispose();
2711

    
2712
            Map<String, VCSGisEntity> tmp = new HashMap<>();
2713
            entities.forEach(entity -> {
2714
                tmp.put(entity.getEntityCode(), entity);
2715
            });
2716
            this.repositoryEntitiesByCode = tmp;
2717
            
2718
            Map<String, EntityRow> theEntitiesByName = new HashMap<>();
2719
            Map<String, EntityRow> theEntitiesByCode = new HashMap<>();
2720

    
2721
            store = openFeatureStore(EntitiesTable.TABLE_NAME);
2722
            store.edit();
2723
            fset = store.getFeatureSet();
2724
            for (Feature feature : fset.iterable()) {
2725
                EntityRow entity = new EntityRow(this, feature);
2726
                VCSGisEntity repositoryEntity = this.repositoryEntitiesByCode.get(entity.getEntityCode());
2727
                if(repositoryEntity != null && !StringUtils.equalsIgnoreCase(entity.getRepositoryRevisionCode(),repositoryEntity.getRepositoryRevisionCode())){
2728
                    entity.setRepositoryRevisionCode(repositoryEntity.getRepositoryRevisionCode());
2729
                    entity.setTopologyPlanCode(repositoryEntity.getTopologyPlanCode());
2730
                    entity.update(store, fset);
2731
                }
2732
                theEntitiesByName.put(entity.getEntityName(), entity);
2733
                theEntitiesByCode.put(entity.getCode(), entity);
2734
            }
2735
            store.finishEditing();
2736
            this.workspaceEntitiesByName = theEntitiesByName;
2737
            this.workspaceEntitiesByCode = theEntitiesByCode;
2738

    
2739
            status.message("Repository tables metadata update completed");
2740
            if (isMyStatus) {
2741
                status.terminate();
2742
            }
2743
            this.repositoryEntitiesChangeListeners.fireEvent();
2744
            this.workspaceEntitiesChangeListeners.fireEvent();
2745
        } catch (VCSGisRuntimeException ex) {
2746
            FeatureStore.cancelEditingQuietly(store);
2747
            status.message("Can't get repository tables metadata");
2748
            if (isMyStatus) {
2749
                status.abort();
2750
            }
2751
            throw ex;
2752
        } catch (Exception ex) {
2753
            FeatureStore.cancelEditingQuietly(store);
2754
            status.message("Can't get repository tables metadata");
2755
            if (isMyStatus) {
2756
                status.abort();
2757
            }
2758
            throw new VCSGisRuntimeException(ERR_CANT_RETRIEVE_ENTITIES, VCSGisUtils.getErrorMessage(ERR_CANT_RETRIEVE_ENTITIES), ex);
2759
        } finally {
2760
            DisposeUtils.disposeQuietly(fset);
2761
            DisposeUtils.disposeQuietly(store);
2762
        }
2763
    }
2764

    
2765
    private boolean hasRepositoryEntities() {
2766
        return this.repositoryEntitiesByCode != null;
2767
    }
2768
    
2769
    @Override
2770
    public List<VCSGisEntity> getRepositoryEntities() {
2771
        if (this.repositoryEntitiesByCode == null) {
2772
            reloadRepositoryEntities(null);
2773
        }
2774
        List<VCSGisEntity> entities = new ArrayList<>(this.repositoryEntitiesByCode.values());
2775
        return entities;
2776
    }
2777

    
2778
    @Override
2779
    public boolean updateNeedMerge(String entityName) {
2780
        RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2781

    
2782
        VCSGisEntity entity = this.getWorkspaceEntity(entityName);
2783
        if (entity == null) {
2784
            entity = this.getRepositoryEntity(entityName);
2785
        }
2786

    
2787
        return remoteChangesTable.updateNeedMerge(this, entity.getEntityCode());
2788
    }
2789

    
2790
    @Override
2791
    public void addToConnectionPool() {
2792
        JDBCServerExplorerParameters params = this.getExplorerParameters();
2793
        DataManager dataManager = DALLocator.getDataManager();
2794
        dataManager.getDataServerExplorerPool().add(this.getLabel(), params);
2795
    }
2796

    
2797
    @Override
2798
    public boolean isInMyDatabase(FeatureStore store) {
2799
        if (!(store.getParameters() instanceof JDBCStoreParameters)) {
2800
            return false;
2801
        }
2802
        JDBCStoreParameters storeParams = (JDBCStoreParameters) store.getParameters();
2803
        JDBCServerExplorerParameters explorerParams = this.getExplorerParameters();
2804
        if (!StringUtils.equalsIgnoreCase(storeParams.getProviderName(), explorerParams.getProviderName())) {
2805
            return false;
2806
        }
2807
        return StringUtils.equalsIgnoreCase(storeParams.getUrl(), explorerParams.getUrl());
2808
    }
2809

    
2810
    @Override
2811
    public int history(String entityName, String group, Timestamp minDate, Timestamp maxDate, int maxNumberOfRevisions, SimpleTaskStatus status) {
2812
        int errcode = ERR_OK;
2813
        if (status == null) {
2814
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2815
                    "History" + entityName
2816
            );
2817
            status.setAutoremove(true);
2818
            status.add();
2819
        }
2820
        if (maxNumberOfRevisions < 0) {
2821
            maxNumberOfRevisions = 1000;
2822
        }
2823
        if (minDate != null && maxDate != null && minDate.compareTo(maxDate) > 0) {
2824
            Timestamp x = minDate;
2825
            minDate = maxDate;
2826
            maxDate = x;
2827
        }
2828
        DataTransaction transaction = DALLocator.getDataManager().createTransaction();
2829
        try {
2830
            LOGGER.debug("===: HISTORY " + this.getCode() + ", '" + this.getLabel() + "', " + entityName);
2831
            reloadWorkspaceEntities();
2832

    
2833
            VCSGisEntity lentity = this.getEntity(entityName);
2834
            if (lentity == null) {
2835
                status.message("Can't find table '" + entityName + "'");
2836
                status.abort();
2837
                return ERR_ENTITY_NOT_EXISTS;
2838
            }
2839

    
2840
            status.message("Executing history request");
2841
            VCSGisHistoryRequest request = this.getRepository().createHistoryRequest(entityName);
2842
            transaction.add(request);
2843

    
2844
            request.setAuthenticationToken(this.authenticationToken);
2845
            request.setUserCode(this.currentUser);
2846
            request.setDateRange(minDate, maxDate);
2847
            request.setMaxNumberOfRevisions(maxNumberOfRevisions);
2848
            request.setRevisionNumberRange(-1, -1);
2849

    
2850
            if ( execute(request) != ERR_OK) {
2851
                status.message("Can't retriev history of " + entityName + " (error " + request.getLastErrorCode() + ")");
2852
                status.abort();
2853
                return request.getLastErrorCode();
2854
            }
2855
            LocalRevisionsTable localRevisionsTable = new LocalRevisionsTable();
2856
            FeatureStore localRevisionsStore = this.openFeatureStore(LocalRevisionsTable.TABLE_NAME);
2857
            transaction.add(localRevisionsStore);
2858
            localRevisionsStore.edit(MODE_PASS_THROUGH);
2859

    
2860
            status.message("Deleting previous local revision information");
2861
            localRevisionsTable.deleteByEntityCodeAndGroup(
2862
                    this,
2863
                    localRevisionsStore,
2864
                    lentity.getEntityCode(),
2865
                    group
2866
            );
2867

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

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

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

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

    
2919
    @Override
2920
    public int history(String entityName, String group, int maxNumberOfRevisions, SimpleTaskStatus status) {
2921
        int errcode = ERR_OK;
2922
        if (status == null) {
2923
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2924
                    "History" + entityName
2925
            );
2926
            status.setAutoremove(true);
2927
            status.add();
2928
        }
2929
        if (maxNumberOfRevisions < 0) {
2930
            maxNumberOfRevisions = 1000;
2931
        }
2932
        DataTransaction transaction = DALLocator.getDataManager().createTransaction();
2933
        try {
2934
            LOGGER.debug("===: HISTORY " + this.getCode() + ", '" + this.getLabel() + "', " + entityName);
2935
            reloadWorkspaceEntities();
2936

    
2937
            EntityRow lentity = this.getWorkspaceEntityByName(entityName);
2938
            if (lentity == null) {
2939
                status.message("Can't find table '" + entityName + "'");
2940
                status.abort();
2941
                return ERR_ENTITY_NOT_EXISTS;
2942
            }
2943
            VarsTable varsTable = new VarsTable();
2944

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

    
2947
            status.message("Executing history request");
2948
            VCSGisHistoryRequest request = this.getRepository().createHistoryRequest(entityName);
2949
            transaction.add(request);
2950

    
2951
            request.setAuthenticationToken(this.authenticationToken);
2952
            request.setUserCode(this.currentUser);
2953
            request.setDateRange(null, null);
2954
            request.setMaxNumberOfRevisions(maxNumberOfRevisions);
2955
            request.setRevisionNumberRange(-1, minRevision);
2956

    
2957
            if ( execute(request) != ERR_OK) {
2958
                status.message("Can't retriev history of " + entityName + " (error " + request.getLastErrorCode() + ")");
2959
                status.abort();
2960
                return request.getLastErrorCode();
2961
            }
2962
            FeatureStore localRevisionsStore = this.openFeatureStore(LocalRevisionsTable.TABLE_NAME);
2963
            transaction.add(localRevisionsStore);
2964
            localRevisionsStore.edit(MODE_PASS_THROUGH);
2965

    
2966
            DisposableIterable<VCSGisRevision> revisions = request.getRevisions();
2967
            status.message("Adding to local revisions");
2968
//            long sz = ContainerUtils.size64(revisions);
2969
//            status.setRangeOfValues(0, sz);
2970
            status.setCurValue(0);
2971

    
2972
            errcode = ERR_CANT_INSERT_FEATURES;
2973
            minRevision = -1;
2974
            Timestamp minDate = now();
2975
            for (VCSGisRevision revision : revisions) {
2976
                LocalRevisionRow row = new LocalRevisionRow(this);
2977
                row.copyFrom(revision);
2978
                row.setGroup(group);
2979
                if (!row.exists(localRevisionsStore)) {
2980
                    row.insert(localRevisionsStore);
2981
                }
2982
                if (minRevision < 0 || minRevision > row.getNumber()) {
2983
                    minRevision = row.getNumber();
2984
                }
2985
                if (minDate.compareTo(row.getRevisionDate()) > 0) {
2986
                    minDate = row.getRevisionDate();
2987
                }
2988
                status.incrementCurrentValue();
2989
            }
2990
            localRevisionsStore.finishEditing();
2991

    
2992
            varsTable.set(
2993
                    this,
2994
                    "history_" + entityName + "_" + group + "_MinDate",
2995
                    minDate.toString()
2996
            );
2997
            varsTable.set(
2998
                    this,
2999
                    "history_" + entityName + "_" + group + "_MinRevision",
3000
                    String.valueOf(minRevision)
3001
            );
3002

    
3003
            transaction.commit();
3004
            status.message("history completed");
3005
            status.terminate();
3006
            return ERR_OK;
3007
        } catch (Exception ex) {
3008
            LOGGER.warn("Can't retrieve history.", ex);
3009
            transaction.rollbackQuietly();
3010
            status.message("Can't retrieve history");
3011
            status.abort();
3012
            return errcode;
3013
        } finally {
3014
            transaction.dispose();
3015
        }
3016
    }
3017

    
3018
    @Override
3019
    public GetItemWithSize64<VCSGisRevision> getRevisions(String entityName, String group) {
3020
        LocalRevisionsTable localRevisionsTable = new LocalRevisionsTable();
3021
        reloadWorkspaceEntities();
3022

    
3023
        VCSGisEntity lentity = this.getEntity(entityName);
3024
        if (lentity == null) {
3025
            throw new IllegalArgumentException("EntityName '" + entityName + "' not found.");
3026
        }
3027
        final VCSGisWorkspaceImpl workspace = this;
3028
        final GetItemWithSizeAndIterator64<Feature> revisionsf = localRevisionsTable.getRevisions(this, lentity.getEntityCode(), group);
3029
        GetItemWithSize64<VCSGisRevision> revisions = new GetItemWithSize64<VCSGisRevision>() {
3030
            @Override
3031
            public long size64() {
3032
                return revisionsf.size64();
3033
            }
3034

    
3035
            @Override
3036
            public VCSGisRevision get64(long position) {
3037
                Feature f = revisionsf.get64(position);
3038
                LocalRevisionRow revision = new LocalRevisionRow(workspace, f);
3039
                return revision;
3040
            }
3041
        };
3042
        return revisions;
3043
    }
3044

    
3045
    @Override
3046
    public String getUserName(String userCode) {
3047
        return null;
3048
    }
3049

    
3050
    @Override
3051
    public VCSGisUser getUser(String userCode) {
3052
        return null;
3053
    }
3054

    
3055
    @Override
3056
    public Feature getRelatedFeature(VCSGisEntity entity, String featureCode) {
3057
        try {
3058
            FeatureStore store = this.getFeatureStore(entity.getEntityName());
3059
            Feature f = store.findFirst("\"" + entity.getFeatureIdFieldName() + "\"='" + featureCode + "'");
3060
            return f;
3061
        } catch (Exception ex) {
3062
            throw new RuntimeException("Can't retrieve feature '" + entity.getEntityName() + "/" + code + "'.", ex);
3063
        }
3064

    
3065
    }
3066

    
3067
    @Override
3068
    public Feature getRelatedFeature(VCSGisRepositoryChange change) {
3069
        EntityRow entity = this.getWorkspaceEntity(change.getEntityCode());
3070
        return getRelatedFeature(entity, change.getRelatedFeatureCode());
3071
    }
3072
    
3073
    @Override
3074
    public int removeEntity(String nameOrCode) {
3075
        int err = ERR_NO_ERROR;
3076
        EntityRow entity = this.getWorkspaceEntity(nameOrCode);
3077
        if(entity == null){
3078
            err = ERR_ENTITY_NOT_EXISTS;
3079
            return err;
3080
        }
3081

    
3082
        DataTransaction transaction = DALLocator.getDataManager().createTransaction();
3083
        try {
3084
            LOGGER.debug("===: REMOVE ENTITY " + entity.getEntityName());
3085

    
3086

    
3087
            //Eliminamos todos los cambios de esta entidad
3088
            err = ERR_CANT_REMOVE_CHANGES;
3089
            FeatureStore changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
3090
            transaction.add(changesStore);
3091
            changesStore.edit(MODE_FULLEDIT);
3092
            changesStore.delete("\""+WorkspaceChangesTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3093
            changesStore.finishEditing();
3094

    
3095
            FeatureStore remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
3096
            transaction.add(remoteChangesStore);
3097
            remoteChangesStore.edit(MODE_FULLEDIT);
3098
            remoteChangesStore.delete("\""+RemoteChangesTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3099
            remoteChangesStore.finishEditing();
3100

    
3101
            //Eliminamos las revisiones locales
3102
            FeatureStore revisionsStore = openFeatureStore(LocalRevisionsTable.TABLE_NAME);       
3103
            transaction.add(revisionsStore);
3104
            revisionsStore.edit(MODE_FULLEDIT);
3105
            revisionsStore.delete("\""+LocalRevisionsTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3106
            revisionsStore.finishEditing();
3107
            err = ERR_CANT_REMOVE_ENTITY;
3108

    
3109

    
3110
            //Eliminamos la entidad
3111
            FeatureStore entitiesStore = openFeatureStore(EntitiesTable.TABLE_NAME);       
3112
            transaction.add(entitiesStore);
3113
            entitiesStore.edit(MODE_FULLEDIT);
3114
            entitiesStore.delete("\""+EntitiesTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3115
            entitiesStore.finishEditing();
3116
            err = ERR_CANT_REMOVE_ENTITY;
3117

    
3118

    
3119
            //Eliminamos el DALFILE
3120
            FeatureStore store = this.openFeatureStore(entity);
3121
            if(store != null){
3122
                transaction.add(store);
3123
                ResourcesStorage resourcesStorage = store.getResourcesStorage();
3124
                if (resourcesStorage != null) {
3125
                    Resource resource = resourcesStorage.getResource("dal");
3126
                    if (resource != null) {
3127
                        resourcesStorage.remove(resource.getName());
3128
                    }
3129
                }
3130
            
3131
                //Eliminamos el store
3132
                transaction.add(this.wsexplorer, false);
3133
                this.wsexplorer.remove(store.getParameters());
3134
            }
3135
            
3136
            forceReloadWorkspaceEntities();
3137
            transaction.commit();
3138
            return ERR_OK;
3139
        } catch (Exception ex) {
3140
            LOGGER.warn("Can't remove entity.", ex);
3141
            transaction.rollbackQuietly();
3142
            return err;
3143
        } finally {
3144
            transaction.dispose();
3145
        }
3146
        
3147
    }
3148

    
3149
    public int authenticate(String userId, String password, SimpleTaskStatus status) {
3150
        int errcode = ERR_OK;
3151
        if (status == null) {
3152
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
3153
                    "Authenticate-" + userId
3154
            );
3155
            status.setAutoremove(true);
3156
            status.add();
3157
        }
3158
        try {
3159
            VCSGisAuthenticateRequest request = this.getRepository().createAuthenticateRequest(userId, password);
3160
            if ( execute(request) != ERR_OK) {
3161
                status.message(request.getLastErrorMessage());
3162
                status.abort();
3163
                return request.getLastErrorCode();
3164
            }
3165
            VarsTable varsTable = new VarsTable();
3166
            varsTable.set(this,"USER",request.getUserCode());
3167
            varsTable.set(this,"AUTHENTICATIONTOKEN",request.getAuthenticationToken());
3168
            this.currentUser = request.getUserCode();
3169
            this.authenticationToken = request.getAuthenticationToken();
3170
            status.message("Authentication completed");
3171
            status.terminate();
3172
            return ERR_OK;
3173
        } catch (Exception ex) {
3174
            LOGGER.warn("Can't authenticate user.", ex);
3175
            status.message("Can't authenticate user");
3176
            status.abort();
3177
            return errcode;
3178
        }
3179
    }
3180

    
3181
    @Override
3182
    public void setUserIdentificationRequester(VCSGisUserIdentificationRequester userIdentificationRequester) {
3183
        this.userIdentificationRequester = userIdentificationRequester;
3184
    }
3185

    
3186
    private int execute(VCSGisRequest request) {
3187
        while(true) {
3188
            switch(request.execute()) {
3189
                case ERR_CANT_AUTHENTICATE_USER:
3190
                case ERR_INVALID_AUTHENTICATION_TOKEN:
3191
                case ERR_USER_NOT_AUTHORIZED:
3192
                case ERR_AUTHENTICATION_EXPIRED:
3193
                case ERR_INVALID_USERCODE:
3194
                    if( this.userIdentificationRequester!= null ) {
3195
                        if( this.userIdentificationRequester.requestIdentification() ) {
3196
                            continue;
3197
                        }
3198
                    }
3199
                default:
3200
                    return request.getLastErrorCode();            
3201
            }
3202
        }
3203
    }
3204

    
3205

    
3206
    // TODO: eliminar la constante y contains para usar las de tools.
3207
    public static final Comparator<String> EQUALS_IGNORECASE_COMPARATOR = (Comparator<String>) (String o1, String o2) -> StringUtils.compareIgnoreCase(o1, o2);
3208
    public static boolean contains(Collection collection, Object value, Comparator comparator) {
3209
        for (Object item : collection) {
3210
            if( comparator.compare(item, value)==0 ) {
3211
                return true;
3212
            }
3213
        }
3214
        return false;
3215
    }
3216

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

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

    
3352
//        FeatureStore entitiesStore = null;
3353

    
3354
        DataTransaction transaction = null;
3355
        try {
3356
            LOGGER.debug("===: REVERT " + this.getCode() + ", " + this.getLabel() + ", " + nameOrCode);
3357
            transaction = DALLocator.getDataManager().createTransaction();
3358
            transaction.begin();
3359
            
3360
            status.message("Reverting");
3361
            
3362
            EntityRow entity = this.getWorkspaceEntity(nameOrCode);
3363
            WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
3364
            FeatureStore userStore = null;
3365
            FeatureStore changesStore = null;
3366
//            String dataCodeFieldName = entity.getFeatureIdFieldName();
3367

    
3368
            DisposableFeatureSetIterable changes = changesTable.getSelectedsByEntityCodeAsIterator(this, entity.getEntityCode());
3369
            transaction.add(changes);
3370

    
3371

    
3372
            if (!changes.isEmpty()) {
3373
                userStore = this.openFeatureStore(entity);
3374
                transaction.add(userStore, true);
3375
                userStore.edit(MODE_PASS_THROUGH);
3376
                changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
3377
                transaction.add(changesStore, true);
3378
                changesStore.edit(MODE_PASS_THROUGH);
3379

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

    
3421
//            LOGGER.debug("===: REVERT: clean local changes");
3422
//            status.message("Removing local list of changes");
3423
//            changesTable.deleteSelectedsByEntity(this, entity.getEntityCode());
3424

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

    
3465
            status.message("Executing export request for " + tableName);
3466
            if ( execute(request) != ERR_OK) {
3467
                status.message("Can't export " + tableName + " (error " + request.getLastErrorCode() + ")");
3468
                status.abort();
3469
                return request.getLastErrorCode();
3470
            }
3471
            status.message("Updating " + tableName + " metadata");
3472
//            VCSGisEntity rentity = request.getEntity();
3473
//            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
3474
//            entitiesStore.edit(FeatureStore.MODE_FULLEDIT);
3475
//            VCSGisEntity rentity = request.getEntity();
3476
//            lentity = new EntityRow(this);
3477
//            rentity.copyto(lentity);
3478
//            lentity.insert(entitiesStore);
3479
//            LOGGER.debug("===: CHECKOUT " + this.getCode() + ", '" + this.getLabel() + "', " + tableName + ", rev." + rentity.getRepositoryRevisionCode());
3480

    
3481
//            this.forceReloadWorkspaceEntities();
3482
            status.message("Creating table " + tableName);
3483
            this.create_table(lentity, tableName);
3484

    
3485
            status.message("Adding features in " + tableName);
3486
            errcode = ERR_CANT_OPEN_STORE;
3487
            target = this.openFeatureStore(tableName);
3488
            this.addStoreIgnoreChanges(target);
3489
            DisposableIterable<VCSGisRepositoryData> data = request.getData();
3490
//            long sz = ContainerUtils.size64(data); // Con tablas tochas esto deja frita la app.
3491
//            status.setRangeOfValues(0, sz);
3492
            status.setCurValue(0);
3493
            errcode = ERR_CANT_INSERT_FEATURES;
3494
            target.edit(FeatureStore.MODE_APPEND);
3495
            for (VCSGisRepositoryData d : data) {
3496
                EditableFeature f = target.createNewFeature(d.getDataAsJson());
3497
                target.insert(f);
3498
                status.incrementCurrentValue();
3499
            }
3500
            target.finishEditing();
3501

    
3502
            status.message("Updating " + tableName + " metadata");
3503
//            if(StringUtils.isBlank(revisionCode)){
3504
//                lentity.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
3505
//            } else {
3506
//                lentity.setLocalRevisionCode(revisionCode);
3507
//            }
3508
//            lentity.update(entitiesStore);
3509
//            entitiesStore.finishEditing();
3510
//            this.forceReloadWorkspaceEntities();
3511
            request.dispose();
3512

    
3513
            status.message("Export completed");
3514
            status.terminate();
3515
            return ERR_NO_ERROR;
3516
        } catch (Exception ex) {
3517
            LOGGER.warn("Can't export.", ex);
3518
            status.message("Can't export");
3519
            status.abort();
3520
            if (target != null) {
3521
                target.cancelEditingQuietly();
3522
            }
3523
            if (entitiesStore != null) {
3524
                entitiesStore.cancelEditingQuietly();
3525
            }
3526
            return errcode;
3527
        } finally {
3528
            DisposeUtils.disposeQuietly(request);
3529
            if (target != null) {
3530
                this.removeStoreIgnoreChanges(target);
3531
            }
3532
            DisposeUtils.disposeQuietly(target);
3533
            DisposeUtils.disposeQuietly(entitiesStore);
3534

    
3535
        }
3536
    }
3537
}