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

History | View | Annotate | Download (152 KB)

1
package org.gvsig.vcsgis.lib.workspace;
2

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
492
    }
493

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

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

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

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

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

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

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

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

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

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

    
680
                }
681

    
682
                return ERR_OK;
683
            }
684

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
843
            this.create_table(entity);
844

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

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

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

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

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

    
997
    }
998

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1177
            entity = this.getWorkspaceEntityByName(name);
1178

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

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

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

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

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

    
1217
            target.finishEditing();
1218

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

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

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

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

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

    
1251
            entitiesStore.edit(MODE_FULLEDIT);
1252

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

    
1256
            entitiesStore.finishEditing();
1257

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

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

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

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

    
1291
        };
1292
        return changes;
1293
    }
1294

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

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

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

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

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

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

    
1387
        };
1388
        return changes;
1389
    }
1390

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1534
        List<VCSGisWorkspaceEntity> entities = 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
                if (change.isSelected()) {
1544
                    entities.add(entity);
1545
                }
1546
            }
1547
            return entities;
1548

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1764
        }
1765
    }
1766
    
1767
    @Override
1768
    public int checkout(List<String> tableNames, SimpleTaskStatus status){
1769
        for (String tableName : tableNames) {
1770
            int r = checkout(tableName, null, status);
1771
            if(r != ERR_NO_ERROR){
1772
                return r;
1773
            }
1774
        }
1775
        return ERR_NO_ERROR;
1776
    }
1777

    
1778

    
1779
    private void updateUsersFromRepository(SimpleTaskStatus status) {
1780
        FeatureStore usersStore = null;
1781
        VCSGisUsersRequest request = null;
1782
        try {
1783
            request = this.getRepository().createUsersRequest();
1784
            request.setAuthenticationToken(this.authenticationToken);
1785
            request.setUserCode(this.currentUserCode);
1786

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

    
1821
            status.message("Executing topology plans request");
1822
            if ( execute(request) != ERR_OK) {
1823
                status.message("Can't get topology plans (error " + request.getLastErrorCode() + ")");
1824
                return;
1825
            }
1826
            status.message("Updating topology plans information");
1827
            topologyPlanStore = this.openFeatureStore(TopologyplanTable.TABLE_NAME);
1828
            topologyPlanStore.edit(FeatureStore.MODE_PASS_THROUGH);
1829
            topologyPlanStore.delete("TRUE");
1830
            for (VCSGisTopologyPlan topologyPlan : request.getTopologyPlans()) {
1831
                TopologyplanTable.TopologyPlanRow row = new TopologyplanTable.TopologyPlanRow(this);
1832
                row.copyFrom(topologyPlan);
1833
                row.insert(topologyPlanStore);
1834
            }
1835
            topologyPlanStore.finishEditing();
1836
            
1837
        } catch(Exception ex) {
1838
            LOGGER.warn("Can't update topology plans.", ex);
1839
            status.message("Can't update topology plans");
1840
            FeatureStore.cancelEditingQuietly(topologyPlanStore);
1841
        } finally {
1842
            DisposeUtils.disposeQuietly(request);
1843
            DisposeUtils.disposeQuietly(topologyPlanStore);
1844
        }     
1845
    }
1846
    
1847
    @Override
1848
    public int updateEntitiesFromRepository() {
1849
        return this.updateEntitiesFromRepository(null);
1850
    }
1851

    
1852
    @Override
1853
    public int updateEntitiesFromRepository(SimpleTaskStatus status) {
1854
        LOGGER.debug("===: UPDATE_ENTITIES " + this.getCode() + ", '" + this.getLabel() + "'");
1855
        FeatureStore entitiesStore = null;
1856
        EntitiesTable entitiesTable = new EntitiesTable();
1857
        if (status == null) {
1858
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Update metadata tables");
1859
            status.setAutoremove(true);
1860
            status.add();
1861
        }
1862
        try {
1863
            status.message("Preparing update metadata tables");
1864
            this.reloadRepositoryEntities(status);
1865

    
1866
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1867
            entitiesStore.edit(MODE_FULLEDIT);
1868
            for (VCSGisEntity rentity : this.getRepositoryEntities()) {
1869
                EntityRow entityRow = entitiesTable.getByEntityName(this, rentity.getEntityName());
1870
                if (entityRow != null) {
1871
                    rentity.copyto(entityRow);
1872
                    entityRow.update(entitiesStore);
1873
                }
1874
            }
1875
            entitiesStore.finishEditingQuietly();
1876

    
1877
            this.reloadWorkspaceEntities();
1878
            status.message("Update metadata tables completed");
1879
            status.terminate();
1880
            return ERR_OK;
1881
        } catch (Exception ex) {
1882
            LOGGER.warn("Can't update metadata tables.", ex);
1883
            status.message("Can't update metadata tables");
1884
            status.abort();
1885
            if (entitiesStore != null) {
1886
                entitiesStore.cancelEditingQuietly();
1887
            }
1888
            return ERR_CANT_UPDATE_ENTITIES;
1889
        } finally {
1890
            DisposeUtils.disposeQuietly(entitiesStore);
1891
            entitiesStore = null;
1892
        }
1893
    }
1894

    
1895
    @Override
1896
    public int updatePrepare(String tableName) {
1897
        return updatePrepare(tableName, null);
1898
    }
1899

    
1900
    @Override
1901
    public int updatePrepare(String tableName, SimpleTaskStatus status) {
1902
        LOGGER.debug("===: UPDATE_PREPARE: " + tableName + " WS " + this.getCode() + ", '" + this.getLabel() + "'");
1903
        if (status == null) {
1904
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Update-prepare " + tableName);
1905
            status.setAutoremove(true);
1906
            status.add();
1907
        }
1908

    
1909
        FeatureStore remoteChangesStore = null;
1910
        VCSGisUpdateRequest request = null;
1911
        DisposableIterable<VCSGisRepositoryData> remoteChanges = null;
1912
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1913
        FeatureStore userStore = null;
1914
        FeatureStore localChangesStore = null;
1915
        FeatureStore entitiesStore = null;
1916
        DataTransaction transaction = null;
1917
        try {
1918
            transaction = DALLocator.getDataManager().createTransaction();
1919
            transaction.begin();
1920
            transaction.add(this.getExplorer(), false);
1921

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

    
1957
            status.message("Preparing remote changes container");
1958
            remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
1959
            transaction.add(remoteChangesStore);
1960
            remoteChangesStore.edit(MODE_PASS_THROUGH);
1961

    
1962
            status.message("Deleting previous temporary remote changes");
1963
            LOGGER.debug("===: UPDATE_PREPARE: Delete updates table");
1964
            remoteChangesStore.delete("\"" + COD_ENTITY + "\"='" + entityCode + "'");
1965

    
1966
            remoteChanges = request.getData();
1967
            transaction.add(remoteChanges);
1968
//            long sz = ContainerUtils.size64(remoteChanges);
1969
//            status.setRangeOfValues(0, sz);
1970
            status.setCurValue(0);
1971

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

    
2003
                if (hasConflictRemoteChangeWithUserTable(lentity, remoteChange, userStore)) {
2004
                    remoteChangeRow.setStatus(STATE_CONFLICT);
2005
                    lentity.setState(STATE_CONFLICT);
2006
                }
2007

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

    
2051
                }
2052
                remoteChangeRow.insert(remoteChangesStore);
2053
                status.incrementCurrentValue();
2054
            }
2055
            LOGGER.debug("===: UPDATE_PREPARE: finish inserting updates");
2056
            lentity.update(entitiesStore);
2057

    
2058
            remoteChangesStore.finishEditing();
2059
            localChangesStore.finishEditing();
2060
            entitiesStore.finishEditing();
2061

    
2062
            updateLocallyModyfiedRemoteChanges();
2063

    
2064
            transaction.commit();
2065

    
2066
            status.message("Update-prepare completed");
2067
            status.terminate();
2068
            return ERR_OK;
2069
        } catch (Exception ex) {
2070
            LOGGER.warn("Can't prepare update.", ex);
2071
            status.message("Can't prepare update");
2072
            status.abort();
2073
            DataTransaction.rollbackQuietly(transaction);
2074
            return ERR_CANT_PREPARE_UPDATE;
2075
        } finally {
2076
            DisposeUtils.disposeQuietly(transaction);
2077
        }
2078

    
2079
    }
2080

    
2081
    private void updateLocallyModyfiedRemoteChanges() {
2082

    
2083
        RemoteChangesTable changes = new RemoteChangesTable();
2084
        changes.updateStateFromLocalChanges(this, STATE_LOCAL_OUTDATED_AND_MODIFIED);
2085

    
2086
    }
2087

    
2088
    private boolean hasConflictRemoteChangeWithUserTable(VCSGisEntity lentity, VCSGisRepositoryData remoteChange, FeatureStore store) throws DataException {
2089
        if (store != null) {
2090
            FeatureType featType = lentity.getFeatureType();
2091
            JsonObject data = remoteChange.getDataAsJson();
2092
            ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
2093
            ExpressionBuilder builder = expManager.createExpressionBuilder();
2094
            builder.set(null);
2095
            for (FeatureAttributeDescriptor attr : featType) {
2096
                if (attr.isIndexed() && !attr.allowIndexDuplicateds()) {
2097
                    Object value = Json.toObject(data, attr.getName());
2098
                    builder.and(
2099
                            builder.eq(
2100
                                    builder.column(attr.getName()),
2101
                                    builder.constant(value)
2102
                            )
2103
                    );
2104

    
2105
                    Feature f = store.findFirst(builder.toString());
2106
                    if (f != null && !StringUtils.equals(
2107
                            f.getString(lentity.getFeatureIdFieldName()),
2108
                            remoteChange.getFeatureRelatedCode())) {
2109
                        return true;
2110
                    }
2111
                }
2112
            }
2113
        }
2114
        return false;
2115
    }
2116

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

    
2182
        FeatureSet feats = store.getFeatureSet(filter.toString());
2183
        return feats.iterable();
2184
    }
2185

    
2186
    @Override
2187
    public int updateClean(String entityCode) {
2188
        return updateClean(entityCode, null);
2189
    }
2190

    
2191
    @Override
2192
    public int updateClean(String entityCode, SimpleTaskStatus status) {
2193
        VCSGisEntity entity = this.getEntity(entityCode);
2194
        if (entity == null) {
2195
            return ERR_ENTITY_NOT_EXISTS;
2196
        }
2197
        if (status == null) {
2198
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2199
                    "Update-clean " + entity.getEntityName()
2200
            );
2201
            status.setAutoremove(true);
2202
            status.add();
2203
        }
2204
        try {
2205
            status.message("Deleting temporary remote changes (" + entity.getEntityName() + ")");
2206
            RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2207
            remoteChangesTable.delete(this, entityCode);
2208
            status.message("Delete temporary remote changes completed");
2209
            status.terminate();
2210
            return ERR_OK;
2211
        } catch (Exception ex) {
2212
            LOGGER.warn("Can't deleting temporary remote changes of " + entity.getEntityName() + ".", ex);
2213
            status.message("Can't deleting temporary remote changes of " + entity.getEntityName() + ".");
2214
            status.abort();
2215
            return ERR_CANT_UPDATE_CLEAN;
2216
        }
2217

    
2218
    }
2219

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

    
2225
    @Override
2226
    public int update(String tableName, SimpleTaskStatus status) {
2227
        return this.update(tableName, false, false, status);
2228
    }
2229

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

    
2235
    @Override
2236
    public int merge(String tableName, SimpleTaskStatus status) {
2237
        return this.update(tableName, false, true, null, status);
2238
    }
2239
    
2240
    @Override
2241
    public int merge(String tableName, MutableLong localChangesCreated, SimpleTaskStatus status) {
2242
        return this.update(tableName, false, true, localChangesCreated, status);
2243
    }
2244

    
2245
    public int update(String tableName, boolean prepare, boolean merge, SimpleTaskStatus status) {
2246
        return update(tableName, prepare, merge, null, status);
2247
    }
2248

    
2249
    public int update(String tableName, boolean prepare, boolean merge, MutableLong localChangesCreated, SimpleTaskStatus status) {
2250
        if(localChangesCreated == null){
2251
            localChangesCreated = new MutableLong(0);
2252
        }
2253
        int errcode = ERR_NO_ERROR;
2254
        if (status == null) {
2255
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2256
                    "Update " + tableName
2257
            );
2258
            status.setAutoremove(true);
2259
            status.add();
2260
        }
2261
        if (prepare) {
2262
            errcode = this.updatePrepare(tableName, status);
2263
            if (errcode != ERR_OK) {
2264
                return errcode;
2265
            }
2266
        }
2267
        LOGGER.debug("===: UPDATE " + this.getCode() + ", '" + this.getLabel() + "', " + tableName);
2268
        RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2269
        WorkspaceChangesTable localChangesTable = new WorkspaceChangesTable();
2270

    
2271
        EditableFeature ef;
2272
        DisposableFeatureSetIterable remoteChanges = null;
2273

    
2274
        FeatureStore workspaceChangesStore = null;
2275
        FeatureStore remoteChangesStore = null;
2276
        FeatureStore userStore = null;
2277
        FeatureStore entitiesStore = null;
2278

    
2279
        DataTransaction transaction = null;
2280
        try {
2281
            transaction = DALLocator.getDataManager().createTransaction();
2282
            transaction.begin();
2283

    
2284
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
2285
            transaction.add(entitiesStore);
2286
            entitiesStore.edit(MODE_PASS_THROUGH);
2287

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

    
2307
            userStore = this.openFeatureStore(lentity);
2308
            if (userStore == null) {
2309
                this.create_table(lentity);
2310
                userStore = this.openFeatureStore(lentity);
2311
            }
2312
            transaction.add(userStore);
2313
            userStore.edit(MODE_PASS_THROUGH);
2314

    
2315
            workspaceChangesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
2316
            transaction.add(workspaceChangesStore);
2317
            workspaceChangesStore.edit(MODE_PASS_THROUGH);
2318

    
2319
            remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
2320
            transaction.add(remoteChangesStore);
2321
            remoteChangesStore.edit(MODE_PASS_THROUGH);
2322

    
2323
            remoteChanges = remoteChangesTable.getSelectedsByEntityCodeAsIterator(this, lentity.getCode());
2324
            transaction.add(remoteChanges);
2325
//            long sz = ContainerUtils.size64(remoteChanges);
2326
//            status.setRangeOfValues(0, sz);
2327
            status.setCurValue(0);
2328

    
2329
            if (!remoteChanges.isEmpty()) {
2330
                this.addStoreIgnoreChanges(userStore);
2331
                status.message("Updating table (" + lentity.getEntityName() + ")");
2332
                FeatureType type = userStore.getDefaultFeatureTypeQuietly();
2333

    
2334
                ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
2335
                ExpressionBuilder builder = expManager.createExpressionBuilder();
2336

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

    
2392
                        case OP_DELETE:
2393
                            LOGGER.debug("===: UPDATE: delete");
2394
                            userStore.delete("\"" + dataCodeFieldName + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2395
//                            workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\"='" + remoteChangeRow.getRelatedFeatureCode()+ "'");
2396
                            break;
2397
                    }
2398
                    status.incrementCurrentValue();
2399
                }
2400
            }
2401

    
2402
            if (merge) {
2403
                status.message("Searching local changes to merge (" + lentity.getEntityName() + ")");
2404
                DisposeUtils.disposeQuietly(remoteChanges);
2405
                remoteChanges = remoteChangesTable.getNotSelectedsByEntityCodeAsIterator(this, lentity.getCode());
2406
                transaction.add(remoteChanges);
2407
//                sz = ContainerUtils.size64(remoteChanges);
2408
//                status.setRangeOfValues(0, sz);
2409
                status.setCurValue(0);
2410

    
2411
                if (!remoteChanges.isEmpty()) {
2412
                    //We edit the changesStore because we will need local changes 
2413
//                    workspaceChangesStore.edit(MODE_PASS_THROUGH);
2414

    
2415
                    //We edit the destination store because we may need to update some features (in case OP_DELETE)
2416
//                    userStore.edit(MODE_PASS_THROUGH);
2417
                    this.addStoreIgnoreChanges(userStore);
2418

    
2419
                    status.message("Adding to local changes (" + lentity.getEntityName() + ")");
2420
                    for (Feature feature : remoteChanges) {
2421
                        RemoteChangeRow remoteChangeRow = new RemoteChangeRow(this, feature);
2422
                        Feature f = userStore.findFirst("\"" + lentity.getFeatureIdFieldName() + "\" = '" + remoteChangeRow.getRelatedFeatureCode() + "'");
2423
                        switch (remoteChangeRow.getOperation()) {
2424
                            case OP_INSERT:
2425
                                LOGGER.debug("===: UPDATE: insert");
2426
                                if (f == null) {
2427
                                    this.addDeleteChange(lentity, workspaceChangesStore, remoteChangeRow.getRelatedFeatureCode(), null, null);
2428
                                } else {
2429
                                    this.addChange(lentity, OP_UPDATE, workspaceChangesStore, f, null);
2430
                                }
2431
                                localChangesCreated.increment();
2432
                                break;
2433

    
2434
                            case OP_UPDATE:
2435
                                LOGGER.debug("===: UPDATE: update");
2436
                                if (f == null) {
2437
                                    this.addDeleteChange(lentity, workspaceChangesStore, remoteChangeRow.getRelatedFeatureCode(), null, null);
2438
                                } else {
2439
                                    this.addChange(lentity, OP_UPDATE, workspaceChangesStore, f, null);
2440
                                }
2441
                                localChangesCreated.increment();
2442
                                break;
2443
                            case OP_DELETE:
2444
                                LOGGER.debug("===: UPDATE: delete");
2445
                                if (f != null) {
2446
                                    userStore.delete("\"" + dataCodeFieldName + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2447

    
2448
                                    ef = userStore.createNewFeature(f);
2449
                                    ef.setString(lentity.getFeatureIdFieldName(), this.createUniqueCode());
2450
                                    userStore.insert(ef);
2451

    
2452
                                    workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2453
                                    this.addChange(lentity, OP_INSERT, workspaceChangesStore, ef, null);
2454
                                    localChangesCreated.increment();
2455
                                }
2456
                                break;
2457
                        }
2458
                        status.incrementCurrentValue();
2459
                    }
2460
                }
2461
            }
2462
            localChangesTable.removeLocalChangesRelatedToSelectedRemoteChanges(this, lentity);
2463
            remoteChangesTable.delete(remoteChangesStore, lentity.getEntityCode());
2464

    
2465
            status.message("Updating metadata tables");
2466
            lentity.setLocalRevisionCode(lentity.getRepositoryRevisionCode());
2467
            lentity.update(entitiesStore);
2468
            forceReloadWorkspaceEntities();
2469

    
2470
            transaction.commit();
2471

    
2472
            status.message("Update completed");
2473
            status.terminate();
2474
            return ERR_OK;
2475
        } catch (Exception ex) {
2476
            LOGGER.warn("Can't update.", ex);
2477
            status.message("Can't update");
2478
            status.abort();
2479
            return ERR_CANT_UPDATE;
2480
        } finally {
2481
            this.removeStoreIgnoreChanges(userStore);
2482
            DisposeUtils.disposeQuietly(transaction);
2483
        }
2484
    }
2485

    
2486
    @Override
2487
    public JDBCServerExplorer getExplorer() {
2488
        return this.wsexplorer;
2489
    }
2490

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

    
2624
            Map<String, VCSGisEntity> tmp = new HashMap<>();
2625
            entities.forEach(entity -> {
2626
                tmp.put(entity.getEntityCode(), entity);
2627
            });
2628
            this.repositoryEntitiesByCode = tmp;
2629
            
2630
            Map<String, EntityRow> theEntitiesByName = new HashMap<>();
2631
            Map<String, EntityRow> theEntitiesByCode = new HashMap<>();
2632

    
2633
            store = openFeatureStore(EntitiesTable.TABLE_NAME);
2634
            store.edit();
2635
            fset = store.getFeatureSet();
2636
            for (Feature feature : fset.iterable()) {
2637
                EntityRow entity = new EntityRow(this, feature);
2638
                VCSGisEntity repositoryEntity = this.repositoryEntitiesByCode.get(entity.getEntityCode());
2639
                if(repositoryEntity != null && !StringUtils.equalsIgnoreCase(entity.getRepositoryRevisionCode(),repositoryEntity.getRepositoryRevisionCode())){
2640
                    entity.setRepositoryRevisionCode(repositoryEntity.getRepositoryRevisionCode());
2641
                    entity.setTopologyPlanCode(repositoryEntity.getTopologyPlanCode());
2642
                    entity.update(store, fset);
2643
                }
2644
                theEntitiesByName.put(entity.getEntityName(), entity);
2645
                theEntitiesByCode.put(entity.getCode(), entity);
2646
            }
2647
            store.finishEditing();
2648
            this.workspaceEntitiesByName = theEntitiesByName;
2649
            this.workspaceEntitiesByCode = theEntitiesByCode;
2650

    
2651
            status.message("Repository tables metadata update completed");
2652
            if (isMyStatus) {
2653
                status.terminate();
2654
            }
2655
            this.repositoryEntitiesChangeListeners.fireEvent();
2656
            this.workspaceEntitiesChangeListeners.fireEvent();
2657
        } catch (VCSGisRuntimeException ex) {
2658
            FeatureStore.cancelEditingQuietly(store);
2659
            status.message("Can't get repository tables metadata");
2660
            if (isMyStatus) {
2661
                status.abort();
2662
            }
2663
            throw ex;
2664
        } catch (Exception ex) {
2665
            FeatureStore.cancelEditingQuietly(store);
2666
            status.message("Can't get repository tables metadata");
2667
            if (isMyStatus) {
2668
                status.abort();
2669
            }
2670
            throw new VCSGisRuntimeException(ERR_CANT_RETRIEVE_ENTITIES, VCSGisUtils.getErrorMessage(ERR_CANT_RETRIEVE_ENTITIES), ex);
2671
        } finally {
2672
            DisposeUtils.disposeQuietly(fset);
2673
            DisposeUtils.disposeQuietly(store);
2674
        }
2675
    }
2676

    
2677
    private boolean hasRepositoryEntities() {
2678
        return this.repositoryEntitiesByCode != null;
2679
    }
2680
    
2681
    @Override
2682
    public List<VCSGisEntity> getRepositoryEntities() {
2683
        if (this.repositoryEntitiesByCode == null) {
2684
            reloadRepositoryEntities(null);
2685
        }
2686
        List<VCSGisEntity> entities = new ArrayList<>(this.repositoryEntitiesByCode.values());
2687
        return entities;
2688
    }
2689

    
2690
    @Override
2691
    public boolean updateNeedMerge(String entityName) {
2692
        RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2693

    
2694
        VCSGisEntity entity = this.getWorkspaceEntity(entityName);
2695
        if (entity == null) {
2696
            entity = this.getRepositoryEntity(entityName);
2697
        }
2698

    
2699
        return remoteChangesTable.updateNeedMerge(this, entity.getEntityCode());
2700
    }
2701

    
2702
    @Override
2703
    public void addToConnectionPool() {
2704
        JDBCServerExplorerParameters params = this.getExplorerParameters();
2705
        DataManager dataManager = DALLocator.getDataManager();
2706
        dataManager.getDataServerExplorerPool().add(this.getLabel(), params);
2707
    }
2708

    
2709
    @Override
2710
    public boolean isInMyDatabase(FeatureStore store) {
2711
        if (!(store.getParameters() instanceof JDBCStoreParameters)) {
2712
            return false;
2713
        }
2714
        JDBCStoreParameters storeParams = (JDBCStoreParameters) store.getParameters();
2715
        JDBCServerExplorerParameters explorerParams = this.getExplorerParameters();
2716
        if (!StringUtils.equalsIgnoreCase(storeParams.getProviderName(), explorerParams.getProviderName())) {
2717
            return false;
2718
        }
2719
        return StringUtils.equalsIgnoreCase(storeParams.getUrl(), explorerParams.getUrl());
2720
    }
2721

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

    
2745
            VCSGisEntity lentity = this.getEntity(entityName);
2746
            if (lentity == null) {
2747
                status.message("Can't find table '" + entityName + "'");
2748
                status.abort();
2749
                return ERR_ENTITY_NOT_EXISTS;
2750
            }
2751

    
2752
            status.message("Executing history request");
2753
            VCSGisHistoryRequest request = this.getRepository().createHistoryRequest(entityName);
2754
            transaction.add(request);
2755

    
2756
            request.setAuthenticationToken(this.authenticationToken);
2757
            request.setUserCode(this.currentUserCode);
2758
            request.setDateRange(minDate, maxDate);
2759
            request.setMaxNumberOfRevisions(maxNumberOfRevisions);
2760
            request.setRevisionNumberRange(-1, -1);
2761

    
2762
            if ( execute(request) != ERR_OK) {
2763
                status.message("Can't retriev history of " + entityName + " (error " + request.getLastErrorCode() + ")");
2764
                status.abort();
2765
                return request.getLastErrorCode();
2766
            }
2767
            LocalRevisionsTable localRevisionsTable = new LocalRevisionsTable();
2768
            FeatureStore localRevisionsStore = this.openFeatureStore(LocalRevisionsTable.TABLE_NAME);
2769
            transaction.add(localRevisionsStore);
2770
            localRevisionsStore.edit(MODE_PASS_THROUGH);
2771

    
2772
            status.message("Deleting previous local revision information");
2773
            localRevisionsTable.deleteByEntityCodeAndGroup(
2774
                    this,
2775
                    localRevisionsStore,
2776
                    lentity.getEntityCode(),
2777
                    group
2778
            );
2779

    
2780
            DisposableIterable<VCSGisRevision> revisions = request.getRevisions();
2781
            status.message("Adding to local revisions");
2782
//            long sz = ContainerUtils.size64(revisions);
2783
//            status.setRangeOfValues(0, sz);
2784
            status.setCurValue(0);
2785

    
2786
            long minRevision = -1;
2787
            minDate = now();
2788
            errcode = ERR_CANT_INSERT_FEATURES;
2789
            for (VCSGisRevision revision : revisions) {
2790
                LocalRevisionRow row = new LocalRevisionRow(this);
2791
                row.copyFrom(revision);
2792
                row.setGroup(group);
2793
                row.insert(localRevisionsStore);
2794
                if (minRevision < 0 || minRevision > row.getNumber()) {
2795
                    minRevision = row.getNumber();
2796
                }
2797
                if (minDate.compareTo(row.getRevisionDate()) > 0) {
2798
                    minDate = row.getRevisionDate();
2799
                }
2800
                status.incrementCurrentValue();
2801
            }
2802
            localRevisionsStore.finishEditing();
2803

    
2804
            VarsTable varsTable = new VarsTable();
2805
            varsTable.set(
2806
                    this,
2807
                    "history_" + entityName + "_" + group + "_MinDate",
2808
                    minDate.toString()
2809
            );
2810
            varsTable.set(
2811
                    this,
2812
                    "history_" + entityName + "_" + group + "_MinRevision",
2813
                    String.valueOf(minRevision)
2814
            );
2815

    
2816
            transaction.commit();
2817
            status.message("History completed");
2818
            status.terminate();
2819
            return ERR_OK;
2820
        } catch (Exception ex) {
2821
            LOGGER.warn("Can't retrieve history.", ex);
2822
            transaction.rollbackQuietly();
2823
            status.message("Can't retrieve history");
2824
            status.abort();
2825
            return errcode;
2826
        } finally {
2827
            transaction.dispose();
2828
        }
2829
    }
2830

    
2831
    @Override
2832
    public int history(String entityName, String group, int maxNumberOfRevisions, SimpleTaskStatus status) {
2833
        int errcode = ERR_OK;
2834
        if (status == null) {
2835
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2836
                    "History" + entityName
2837
            );
2838
            status.setAutoremove(true);
2839
            status.add();
2840
        }
2841
        if (maxNumberOfRevisions < 0) {
2842
            maxNumberOfRevisions = 1000;
2843
        }
2844
        DataTransaction transaction = DALLocator.getDataManager().createTransaction();
2845
        try {
2846
            LOGGER.debug("===: HISTORY " + this.getCode() + ", '" + this.getLabel() + "', " + entityName);
2847
            reloadWorkspaceEntities();
2848

    
2849
            EntityRow lentity = this.getWorkspaceEntityByName(entityName);
2850
            if (lentity == null) {
2851
                status.message("Can't find table '" + entityName + "'");
2852
                status.abort();
2853
                return ERR_ENTITY_NOT_EXISTS;
2854
            }
2855
            VarsTable varsTable = new VarsTable();
2856

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

    
2859
            status.message("Executing history request");
2860
            VCSGisHistoryRequest request = this.getRepository().createHistoryRequest(entityName);
2861
            transaction.add(request);
2862

    
2863
            request.setAuthenticationToken(this.authenticationToken);
2864
            request.setUserCode(this.currentUserCode);
2865
            request.setDateRange(null, null);
2866
            request.setMaxNumberOfRevisions(maxNumberOfRevisions);
2867
            request.setRevisionNumberRange(-1, minRevision);
2868

    
2869
            if ( execute(request) != ERR_OK) {
2870
                status.message("Can't retriev history of " + entityName + " (error " + request.getLastErrorCode() + ")");
2871
                status.abort();
2872
                return request.getLastErrorCode();
2873
            }
2874
            FeatureStore localRevisionsStore = this.openFeatureStore(LocalRevisionsTable.TABLE_NAME);
2875
            transaction.add(localRevisionsStore);
2876
            localRevisionsStore.edit(MODE_PASS_THROUGH);
2877

    
2878
            DisposableIterable<VCSGisRevision> revisions = request.getRevisions();
2879
            status.message("Adding to local revisions");
2880
//            long sz = ContainerUtils.size64(revisions);
2881
//            status.setRangeOfValues(0, sz);
2882
            status.setCurValue(0);
2883

    
2884
            errcode = ERR_CANT_INSERT_FEATURES;
2885
            minRevision = -1;
2886
            Timestamp minDate = now();
2887
            for (VCSGisRevision revision : revisions) {
2888
                LocalRevisionRow row = new LocalRevisionRow(this);
2889
                row.copyFrom(revision);
2890
                row.setGroup(group);
2891
                if (!row.exists(localRevisionsStore)) {
2892
                    row.insert(localRevisionsStore);
2893
                }
2894
                if (minRevision < 0 || minRevision > row.getNumber()) {
2895
                    minRevision = row.getNumber();
2896
                }
2897
                if (minDate.compareTo(row.getRevisionDate()) > 0) {
2898
                    minDate = row.getRevisionDate();
2899
                }
2900
                status.incrementCurrentValue();
2901
            }
2902
            localRevisionsStore.finishEditing();
2903

    
2904
            varsTable.set(
2905
                    this,
2906
                    "history_" + entityName + "_" + group + "_MinDate",
2907
                    minDate.toString()
2908
            );
2909
            varsTable.set(
2910
                    this,
2911
                    "history_" + entityName + "_" + group + "_MinRevision",
2912
                    String.valueOf(minRevision)
2913
            );
2914

    
2915
            transaction.commit();
2916
            status.message("history completed");
2917
            status.terminate();
2918
            return ERR_OK;
2919
        } catch (Exception ex) {
2920
            LOGGER.warn("Can't retrieve history.", ex);
2921
            transaction.rollbackQuietly();
2922
            status.message("Can't retrieve history");
2923
            status.abort();
2924
            return errcode;
2925
        } finally {
2926
            transaction.dispose();
2927
        }
2928
    }
2929

    
2930
    @Override
2931
    public GetItemWithSize64<VCSGisRevision> getRevisions(String entityName, String group) {
2932
        LocalRevisionsTable localRevisionsTable = new LocalRevisionsTable();
2933
        reloadWorkspaceEntities();
2934

    
2935
        VCSGisEntity lentity = this.getEntity(entityName);
2936
        if (lentity == null) {
2937
            throw new IllegalArgumentException("EntityName '" + entityName + "' not found.");
2938
        }
2939
        final VCSGisWorkspaceImpl workspace = this;
2940
        final GetItemWithSizeAndIterator64<Feature> revisionsf = localRevisionsTable.getRevisions(this, lentity.getEntityCode(), group);
2941
        GetItemWithSize64<VCSGisRevision> revisions = new GetItemWithSize64<VCSGisRevision>() {
2942
            @Override
2943
            public long size64() {
2944
                return revisionsf.size64();
2945
            }
2946

    
2947
            @Override
2948
            public VCSGisRevision get64(long position) {
2949
                Feature f = revisionsf.get64(position);
2950
                LocalRevisionRow revision = new LocalRevisionRow(workspace, f);
2951
                return revision;
2952
            }
2953
        };
2954
        return revisions;
2955
    }
2956

    
2957
    @Override
2958
    public String getUserName(String userCode) {
2959
        return null;
2960
    }
2961

    
2962
    @Override
2963
    public VCSGisUser getUser(String userCode) {
2964
        return null;
2965
    }
2966

    
2967
    @Override
2968
    public Feature getRelatedFeature(VCSGisEntity entity, String featureCode) {
2969
        try {
2970
            FeatureStore store = this.getFeatureStore(entity.getEntityName());
2971
            Feature f = store.findFirst("\"" + entity.getFeatureIdFieldName() + "\"='" + featureCode + "'");
2972
            return f;
2973
        } catch (Exception ex) {
2974
            throw new RuntimeException("Can't retrieve feature '" + entity.getEntityName() + "/" + code + "'.", ex);
2975
        }
2976

    
2977
    }
2978

    
2979
    @Override
2980
    public Feature getRelatedFeature(VCSGisRepositoryChange change) {
2981
        EntityRow entity = this.getWorkspaceEntity(change.getEntityCode());
2982
        return getRelatedFeature(entity, change.getRelatedFeatureCode());
2983
    }
2984
    
2985
    @Override
2986
    public int removeEntity(String nameOrCode) {
2987
        int err = ERR_NO_ERROR;
2988
        EntityRow entity = this.getWorkspaceEntity(nameOrCode);
2989
        if(entity == null){
2990
            err = ERR_ENTITY_NOT_EXISTS;
2991
            return err;
2992
        }
2993

    
2994
        DataTransaction transaction = DALLocator.getDataManager().createTransaction();
2995
        try {
2996
            err = doRemoveEntity(entity, transaction);
2997
            forceReloadWorkspaceEntities();
2998
            transaction.commit();
2999
            return ERR_OK;
3000
        } catch (Exception ex) {
3001
            LOGGER.warn("Can't remove entity.", ex);
3002
            transaction.rollbackQuietly();
3003
            return err;
3004
        } finally {
3005
            transaction.dispose();
3006
        }
3007
    }
3008

    
3009
    @Override
3010
    public int removeEntities(List<String> namesOrCodes) {
3011
        int err = ERR_NO_ERROR;
3012
        DataTransaction transaction = DALLocator.getDataManager().createTransaction();
3013
        
3014
        try {
3015
            for (String nameOrCode : namesOrCodes) {
3016
                EntityRow entity = this.getWorkspaceEntity(nameOrCode);
3017
                if(entity == null){
3018
                    err = ERR_ENTITY_NOT_EXISTS;
3019
                    return err;
3020
                }
3021

    
3022
                doRemoveEntity(entity, transaction);
3023
            }
3024
            
3025
            forceReloadWorkspaceEntities();
3026
            transaction.commit();
3027
            return ERR_OK;
3028
        } catch (Exception ex) {
3029
            LOGGER.warn("Can't remove entity.", ex);
3030
            transaction.rollbackQuietly();
3031
            return err;
3032
        } finally {
3033
            transaction.dispose();
3034
        }
3035
        
3036
    }
3037

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

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

    
3147
    @Override
3148
    public void setUserIdentificationRequester(VCSGisUserIdentificationRequester userIdentificationRequester) {
3149
        this.userIdentificationRequester = userIdentificationRequester;
3150
    }
3151

    
3152
    @Override
3153
    public VCSGisUserIdentificationRequester getUserIdentificationRequester() {
3154
        return this.userIdentificationRequester;
3155
    }
3156

    
3157
    private int execute(VCSGisRequest request) {
3158
        while(true) {
3159
            switch(request.execute()) {
3160
                case ERR_CANT_AUTHENTICATE_USER:
3161
                case ERR_INVALID_AUTHENTICATION_TOKEN:
3162
                case ERR_USER_NOT_AUTHORIZED:
3163
                case ERR_AUTHENTICATION_EXPIRED:
3164
                case ERR_INVALID_USERCODE:
3165
                    if( this.userIdentificationRequester!= null ) {
3166
                        if( this.userIdentificationRequester.requestIdentification() ) {
3167
                            int r = this.authenticate(this.userIdentificationRequester.getUserId(), this.userIdentificationRequester.getPassword(), null);
3168
                            if(r == ERR_OK){
3169
                                request.setAuthenticationToken(this.authenticationToken);
3170
                                request.setUserCode(this.currentUserCode);
3171
                            }
3172
                            continue;
3173
                        }
3174
                    }
3175
                    // don't break
3176
                default:
3177
                    return request.getLastErrorCode();            
3178
            }
3179
        }
3180
    }
3181

    
3182

    
3183
    // TODO: eliminar la constante y contains para usar las de tools.
3184
    public static final Comparator<String> EQUALS_IGNORECASE_COMPARATOR = (Comparator<String>) (String o1, String o2) -> StringUtils.compareIgnoreCase(o1, o2);
3185
    public static boolean contains(Collection collection, Object value, Comparator comparator) {
3186
        for (Object item : collection) {
3187
            if( comparator.compare(item, value)==0 ) {
3188
                return true;
3189
            }
3190
        }
3191
        return false;
3192
    }
3193

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

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

    
3329
//        FeatureStore entitiesStore = null;
3330

    
3331
        DataTransaction transaction = null;
3332
        try {
3333
            LOGGER.debug("===: REVERT " + this.getCode() + ", " + this.getLabel() + ", " + nameOrCode);
3334
            transaction = DALLocator.getDataManager().createTransaction();
3335
            transaction.begin();
3336
            
3337
            status.message("Reverting");
3338
            
3339
            EntityRow entity = this.getWorkspaceEntity(nameOrCode);
3340
            WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
3341
            FeatureStore userStore = null;
3342
            FeatureStore changesStore = null;
3343
//            String dataCodeFieldName = entity.getFeatureIdFieldName();
3344

    
3345
            DisposableFeatureSetIterable changes = changesTable.getSelectedsByEntityCodeAsIterator(this, entity.getEntityCode());
3346
            transaction.add(changes);
3347

    
3348

    
3349
            if (!changes.isEmpty()) {
3350
                userStore = this.openFeatureStore(entity);
3351
                transaction.add(userStore, true);
3352
                userStore.edit(MODE_PASS_THROUGH);
3353
                changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
3354
                transaction.add(changesStore, true);
3355
                changesStore.edit(MODE_PASS_THROUGH);
3356

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

    
3398
//            LOGGER.debug("===: REVERT: clean local changes");
3399
//            status.message("Removing local list of changes");
3400
//            changesTable.deleteSelectedsByEntity(this, entity.getEntityCode());
3401

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

    
3442
            status.message("Executing export request for " + tableName);
3443
            if ( execute(request) != ERR_OK) {
3444
                status.message("Can't export " + tableName + " (error " + request.getLastErrorCode() + ")");
3445
                status.abort();
3446
                return request.getLastErrorCode();
3447
            }
3448
            status.message("Updating " + tableName + " metadata");
3449
//            VCSGisEntity rentity = request.getEntity();
3450
//            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
3451
//            entitiesStore.edit(FeatureStore.MODE_FULLEDIT);
3452
//            VCSGisEntity rentity = request.getEntity();
3453
//            lentity = new EntityRow(this);
3454
//            rentity.copyto(lentity);
3455
//            lentity.insert(entitiesStore);
3456
//            LOGGER.debug("===: CHECKOUT " + this.getCode() + ", '" + this.getLabel() + "', " + tableName + ", rev." + rentity.getRepositoryRevisionCode());
3457

    
3458
//            this.forceReloadWorkspaceEntities();
3459
            status.message("Creating table " + tableName);
3460
            this.create_table(lentity, tableName);
3461

    
3462
            status.message("Adding features in " + tableName);
3463
            errcode = ERR_CANT_OPEN_STORE;
3464
            target = this.openFeatureStore(tableName);
3465
            this.addStoreIgnoreChanges(target);
3466
            DisposableIterable<VCSGisRepositoryData> data = request.getData();
3467
//            long sz = ContainerUtils.size64(data); // Con tablas tochas esto deja frita la app.
3468
//            status.setRangeOfValues(0, sz);
3469
            status.setCurValue(0);
3470
            errcode = ERR_CANT_INSERT_FEATURES;
3471
            target.edit(FeatureStore.MODE_APPEND);
3472
            for (VCSGisRepositoryData d : data) {
3473
                EditableFeature f = target.createNewFeature(d.getDataAsJson());
3474
                target.insert(f);
3475
                status.incrementCurrentValue();
3476
            }
3477
            target.finishEditing();
3478

    
3479
            status.message("Updating " + tableName + " metadata");
3480
//            if(StringUtils.isBlank(revisionCode)){
3481
//                lentity.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
3482
//            } else {
3483
//                lentity.setLocalRevisionCode(revisionCode);
3484
//            }
3485
//            lentity.update(entitiesStore);
3486
//            entitiesStore.finishEditing();
3487
//            this.forceReloadWorkspaceEntities();
3488
            request.dispose();
3489

    
3490
            status.message("Export completed");
3491
            status.terminate();
3492
            return ERR_NO_ERROR;
3493
        } catch (Exception ex) {
3494
            LOGGER.warn("Can't export.", ex);
3495
            status.message("Can't export");
3496
            status.abort();
3497
            if (target != null) {
3498
                target.cancelEditingQuietly();
3499
            }
3500
            if (entitiesStore != null) {
3501
                entitiesStore.cancelEditingQuietly();
3502
            }
3503
            return errcode;
3504
        } finally {
3505
            DisposeUtils.disposeQuietly(request);
3506
            if (target != null) {
3507
                this.removeStoreIgnoreChanges(target);
3508
            }
3509
            DisposeUtils.disposeQuietly(target);
3510
            DisposeUtils.disposeQuietly(entitiesStore);
3511

    
3512
        }
3513
    }
3514

    
3515
    @Override
3516
    public List<String> getDataModels() {
3517
        List<VCSGisEntity> rEntities = getRepositoryEntities();
3518
        Set<String> dataModels = new HashSet();
3519
        for (VCSGisEntity entity : rEntities) {
3520
            List<String> dataModelsEntity = entity.getDataModelsAsList();
3521
            dataModels.addAll(dataModelsEntity);
3522
        }
3523
        return new ArrayList<>(dataModels);
3524
    }
3525
}