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

History | View | Annotate | Download (70.9 KB)

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

    
3
import java.io.File;
4
import java.sql.Timestamp;
5
import java.time.LocalDateTime;
6
import java.time.ZoneOffset;
7
import java.util.ArrayList;
8
import java.util.Collection;
9
import java.util.HashMap;
10
import java.util.HashSet;
11
import java.util.Iterator;
12
import java.util.List;
13
import java.util.Map;
14
import java.util.Set;
15
import javax.json.JsonObject;
16
import org.apache.commons.lang3.Range;
17
import org.apache.commons.lang3.StringUtils;
18
import org.gvsig.expressionevaluator.ExpressionBuilder;
19
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
20
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
21
import org.gvsig.fmap.dal.DALLocator;
22
import org.gvsig.fmap.dal.DataManager;
23
import org.gvsig.fmap.dal.DataStore;
24
import org.gvsig.fmap.dal.DataStoreParameters;
25
import org.gvsig.fmap.dal.feature.EditableFeature;
26
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
27
import org.gvsig.fmap.dal.feature.EditableFeatureType;
28
import org.gvsig.fmap.dal.feature.Feature;
29
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
30
import org.gvsig.fmap.dal.feature.FeatureReference;
31
import org.gvsig.fmap.dal.feature.FeatureSet.DisposableFeatureSetIterable;
32
import org.gvsig.fmap.dal.feature.FeatureStore;
33
import static org.gvsig.fmap.dal.feature.FeatureStore.MODE_PASS_THROUGH;
34
import org.gvsig.fmap.dal.feature.FeatureType;
35
import org.gvsig.fmap.dal.store.jdbc.JDBCNewStoreParameters;
36
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorerParameters;
37
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
38
import org.gvsig.fmap.dal.store.jdbc2.JDBCServerExplorer;
39
import org.gvsig.json.Json;
40
import org.gvsig.tools.ToolsLocator;
41
import org.gvsig.tools.dataTypes.DataTypes;
42
import org.gvsig.tools.dispose.DisposableIterable;
43
import org.gvsig.tools.dispose.DisposeUtils;
44
import org.gvsig.tools.logger.FilteredLogger;
45
import org.gvsig.tools.task.SimpleTaskStatus;
46
import org.gvsig.tools.util.ContainerUtils;
47
import org.gvsig.tools.util.GetItemWithSizeAndIterator64;
48
import org.gvsig.tools.util.HasAFile;
49
import org.gvsig.vcsgis.lib.DisposableIterableAdapter;
50
import org.gvsig.vcsgis.lib.VCSGisChange;
51
import org.gvsig.vcsgis.lib.VCSGisCodeGenerator;
52
import org.gvsig.vcsgis.lib.VCSGisEntity;
53
import static org.gvsig.vcsgis.lib.VCSGisManager.DEFAULT_DATA_TABLE;
54
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_ADD_CHANGE;
55
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_COMMIT;
56
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_INSERT_CHANGE;
57
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_INSERT_FEATURES;
58
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_OPEN_CHANGES;
59
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_OPEN_ENTITIES;
60
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_OPEN_STORE;
61
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_PREPARE_UPDATE;
62
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_RETRIEVE_SOURCE_FEATURES;
63
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_UPDATE;
64
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_UPDATE_CLEAN;
65
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_CANT_UPDATE_ENTITIES;
66
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_ENTITY_ALREADY_EXISTS;
67
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_ENTITY_NOT_EXISTS;
68
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_ENTITY_NOT_HAS_VCSGISCODE;
69
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_NO_ERROR;
70
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_OK;
71
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_STORE_NOT_IN_VERSION_CONTROL;
72
import static org.gvsig.vcsgis.lib.VCSGisManager.ERR_UPDATE_NEED_MERGE;
73
import static org.gvsig.vcsgis.lib.VCSGisManager.FEATURECODE_FIELD_NAME;
74
import static org.gvsig.vcsgis.lib.VCSGisManager.OP_ADD_ENTITY;
75
import static org.gvsig.vcsgis.lib.VCSGisManager.OP_DELETE;
76
import static org.gvsig.vcsgis.lib.VCSGisManager.OP_INSERT;
77
import static org.gvsig.vcsgis.lib.VCSGisManager.OP_UPDATE;
78
import static org.gvsig.vcsgis.lib.VCSGisManager.STATE_MODIFIED;
79
import static org.gvsig.vcsgis.lib.VCSGisManager.STATE_NEW;
80
import static org.gvsig.vcsgis.lib.VCSGisManager.STATE_OUTDATED;
81
import static org.gvsig.vcsgis.lib.VCSGisManager.STATE_OUTDATED_AND_MODIFIED;
82
import static org.gvsig.vcsgis.lib.VCSGisManager.STATE_UNMODIFIED;
83
import static org.gvsig.vcsgis.lib.VCSGisManagerImpl.INTERNAL_TABLES;
84
import org.gvsig.vcsgis.lib.VCSGisRevision;
85
import org.gvsig.vcsgis.lib.VCSGisRuntimeException;
86
import org.gvsig.vcsgis.lib.VCSGisUtils;
87
import org.gvsig.vcsgis.lib.repository.VCSGisRepository;
88
import org.gvsig.vcsgis.lib.repository.VCSGisRepositoryChange;
89
import org.gvsig.vcsgis.lib.repository.VCSGisRepositoryData;
90
import org.gvsig.vcsgis.lib.repository.localdb.VCSGisRepositoryLocaldb;
91
import org.gvsig.vcsgis.lib.repository.localdb.tables.EntitiesRepoTable;
92
import org.gvsig.vcsgis.lib.repository.requests.VCSGisCheckoutRequest;
93
import org.gvsig.vcsgis.lib.repository.requests.VCSGisCommitRequest;
94
import org.gvsig.vcsgis.lib.repository.requests.VCSGisEntitiesRequest;
95
import org.gvsig.vcsgis.lib.repository.requests.VCSGisLogRequest;
96
import org.gvsig.vcsgis.lib.repository.requests.VCSGisUpdateRequest;
97
import org.gvsig.vcsgis.lib.workspace.tables.EntitiesTable;
98
import org.gvsig.vcsgis.lib.workspace.tables.EntitiesTable.EntityRow;
99
import org.gvsig.vcsgis.lib.workspace.tables.LocalRevisionsTable;
100
import org.gvsig.vcsgis.lib.workspace.tables.LocalRevisionsTable.LocalRevisionRow;
101
import org.gvsig.vcsgis.lib.workspace.tables.RemoteChangesTable;
102
import static org.gvsig.vcsgis.lib.workspace.tables.RemoteChangesTable.COD_ENTITY;
103
import org.gvsig.vcsgis.lib.workspace.tables.RemoteChangesTable.RemoteChangeRow;
104
import org.gvsig.vcsgis.lib.workspace.tables.VarsTable;
105
import org.gvsig.vcsgis.lib.workspace.tables.WorkspaceChangesTable;
106
import org.gvsig.vcsgis.lib.workspace.tables.WorkspaceChangesTable.WorkspaceChangeRow;
107
import org.slf4j.Logger;
108
import org.slf4j.LoggerFactory;
109

    
110
/**
111
 *
112
 * @author gvSIG Team
113
 */
114
@SuppressWarnings({"UseSpecificCatch", "UnusedAssignment"})
115
public class VCSGisWorkspaceImpl implements VCSGisWorkspace {
116

    
117
    private static final Logger LOGGER = LoggerFactory.getLogger(VCSGisWorkspaceImpl.class);
118

    
119
    private final Map<String, FeatureStore> storesCache;
120
    private Map<String, EntityRow> workspaceEntitiesByName;
121
    private Map<String, EntityRow> workspaceEntitiesByCode;
122
    private Map<String, VCSGisEntity> repositoryEntitiesByCode;
123
    private Set<FeatureStore> storeIgnoreChanges;
124
    private JDBCServerExplorer wsexplorer;
125
    private String code;
126
    private final VCSGisRepository repository;
127
    private final String label;
128
    private final FilteredLogger logger;
129
    private final VCSGisCodeGenerator codeGenerator;
130
   
131
    public VCSGisWorkspaceImpl(JDBCServerExplorer wsexplorer, VCSGisCodeGenerator codeGenerator, VCSGisRepository repository, String label) {
132
        this.logger = new FilteredLogger(LOGGER, "VCSGisWorkspace", 100);
133
        this.logger.setInterval(10000);
134
        this.codeGenerator = codeGenerator;
135
        this.storesCache = new HashMap<>();
136
        this.code = createUniqueCode();
137
        this.wsexplorer = wsexplorer;
138
        this.repository = repository;
139
        this.label = label;
140
//        LOGGER.debug("===: CREATE WORKSPACE "+ hexId(this)+ " (init label='"+this.label+"')");
141
        
142
    }
143

    
144
    public VCSGisWorkspaceImpl(JDBCServerExplorer wsexplorer, VCSGisCodeGenerator codeGenerator) {
145
        this.logger = new FilteredLogger(LOGGER, "VCSGisWorkspace", 100);
146
        this.logger.setInterval(10000);
147
        this.codeGenerator = codeGenerator;
148
        this.storesCache = new HashMap<>();
149
        this.wsexplorer = wsexplorer;
150
        this.loadEntities();
151

    
152
        VarsTable varsTable = new VarsTable();
153
        this.code = varsTable.get(this, "WORKSPACE_CODE");
154
        if (this.code == null) {
155
            throw new RuntimeException("Can't retrieve code from workspace '" + this.getMessageLabel() + "'");
156
        }
157
        this.repository = (VCSGisRepository) Json.toObject(varsTable.get(this, "REPOSITORY"));
158
        if (this.repository == null) {
159
            throw new RuntimeException("Can't retrieve repository from workspace '" + this.getMessageLabel() + "'");
160
        }
161
        this.label = varsTable.get(this, "WORKSPACE_LABEL");
162
//        LOGGER.debug("===: CREATE WORKSPACE "+ hexId(this)+ " (open code='"+this.code+"', label='"+this.label+"')");
163
    }
164
    
165
    public void initialize() throws Exception {
166
        DataManager dataManager = DALLocator.getDataManager();
167
            
168
//        List<VCSGisEntity> rentities = this.getRepositoryEntities();
169
//        if (!rentities.isEmpty()) {
170
//            JDBCStoreParameters storeParams = wsexplorer.get(EntitiesTable.TABLE_NAME);
171
//            FeatureStore storeEntities = (FeatureStore) dataManager.openStore(
172
//                    DataStore.H2SPATIAL_PROVIDER_NAME,
173
//                    storeParams
174
//            );
175
//            storeEntities.edit(FeatureStore.MODE_APPEND);
176
//            for (VCSGisEntity rentity : rentities) {
177
//                EntityRow entity = new EntityRow(this, storeEntities.createNewFeature());
178
//                entity.copyfrom(rentity);
179
//                entity.setLocalRevisionCode(null);
180
//                entity.insert(storeEntities);
181
//            }
182
//            storeEntities.finishEditing();
183
//        }
184
        VarsTable varsTable = new VarsTable();
185
        varsTable.set(this, "WORKSPACE_CODE", code);
186
        varsTable.set(this, "WORKSPACE_LABEL", label);
187
        varsTable.set(this, "REPOSITORY", repository.toJson().toString());
188
    }
189
    
190
    private String getMessageLabel() {
191
        return this.wsexplorer.getParameters().getUrl();
192
    }
193

    
194
    @Override
195
    public String getCode() {
196
        return this.code;
197
    }
198

    
199
    @Override
200
    public String getLabel() {
201
        return this.label;
202
    }
203

    
204
    @Override
205
    public void dispose() {
206
        for (Map.Entry<String, FeatureStore> entry : storesCache.entrySet()) {
207
            FeatureStore store = entry.getValue();
208
            if (store != null) {
209
                DisposeUtils.disposeQuietly(store);
210
            }
211
        }
212
        this.storesCache.clear();
213
        DisposeUtils.dispose(this.wsexplorer);
214
        this.wsexplorer= null;
215
        this.code = null;
216
    }
217

    
218
    @Override
219
    public JDBCServerExplorerParameters getExplorerParameters() {
220
        return this.wsexplorer.getParameters();
221
    }
222

    
223
    private boolean isInStoreIgnoreChanges(FeatureStore store) {
224
        if (this.storeIgnoreChanges == null) {
225
            return false;
226
        }
227
        return this.storeIgnoreChanges.contains(store);
228
    }
229

    
230
    private void addStoreIgnoreChanges(FeatureStore store) {
231
        if (this.storeIgnoreChanges == null) {
232
            this.storeIgnoreChanges = new HashSet<>();
233
        }
234
        this.storeIgnoreChanges.add(store);
235
    }
236

    
237
    private void removeStoreIgnoreChanges(FeatureStore store) {
238
        if (this.storeIgnoreChanges == null) {
239
            this.storeIgnoreChanges = new HashSet<>();
240
        }
241
        this.storeIgnoreChanges.remove(store);
242
    }
243

    
244
//    private boolean contains(FeatureStore store) {
245
//        return this.getEntity(store) != null;
246
//    }
247
//
248
    private EntityRow getEntity(FeatureStore store) {
249
        String s = (String) store.getProperty("VCSGIS_WORKSPACE");
250
        if (s != null) {
251
            if (StringUtils.equalsIgnoreCase(code, s)) {
252
                return this.getWorkspaceEntityByName((String) store.getProperty("VCSGIS_ENTITY"));
253
            }
254
            return null;
255
        }
256

    
257
        DataStoreParameters params = store.getParameters();
258
        if (!DataStore.H2SPATIAL_PROVIDER_NAME.equalsIgnoreCase(params.getProviderName())) {
259
            store.setProperty("VCSGIS_WORKSPACE", "#########");
260
            return null;
261
        }
262

    
263
        File f = ((HasAFile) params).getFile();
264
        if (f == null) {
265
            store.setProperty("VCSGIS_WORKSPACE", "#########");
266
            return null;
267
        }
268
        EntityRow entity = this.getWorkspaceEntityByName(((JDBCStoreParameters) params).getTable());
269
        if (entity == null) {
270
            store.setProperty("VCSGIS_WORKSPACE", "#########");
271
            return null;
272
        }
273
        store.setProperty("VCSGIS_WORKSPACE", this.code);
274
        store.setProperty("VCSGIS_ENTITY", entity.getEntityName());
275

    
276
        return entity;
277
    }
278

    
279
    private void loadEntities() {
280
        FeatureStore store = null;
281
        try {
282
            Map<String, EntityRow> theEntitiesByName = new HashMap<>();
283
            Map<String, EntityRow> theEntitiesByCode = new HashMap<>();
284
            store = getFeatureStore(EntitiesTable.TABLE_NAME);
285
            for (Feature feature : store.getFeatureSet().iterable()) {
286
                EntityRow entity = new EntityRow(this, feature);
287
                theEntitiesByName.put(entity.getEntityName(), entity);
288
                theEntitiesByCode.put(entity.getCode(), entity);
289
                LOGGER.debug("===: loadEntities: "+entity.getEntityName()+" entity code "+entity.getEntityCode()+", repo rev. "+entity.getRepositoryRevisionCode()+", local rev. "+entity.getLocalRevisionCode());            
290
            }
291
            this.workspaceEntitiesByName = theEntitiesByName;
292
            this.workspaceEntitiesByCode = theEntitiesByCode;
293
        } catch (Exception ex) {
294
            LOGGER.warn("Can't load entity information.", ex);
295
        } finally {
296
            DisposeUtils.disposeQuietly(store);
297
        }
298
    }
299

    
300
    @Override
301
    public List<VCSGisWorkspaceEntity> getWorkspaceEntities() {
302
        List<VCSGisWorkspaceEntity> entities = new ArrayList<>();
303
        entities.addAll(this.getEntitiesAsEntityRow());
304
        return entities;
305
    }
306

    
307
    private Collection<EntityRow> getEntitiesAsEntityRow() {
308
        if (this.workspaceEntitiesByName == null) {
309
            loadEntities();
310
        }
311
        return this.workspaceEntitiesByName.values();
312
    }
313

    
314
    @Override
315
    public EntityRow getWorkspaceEntityByName(String name) {
316
        if (this.workspaceEntitiesByName == null) {
317
            this.loadEntities();
318
        }
319
        return this.workspaceEntitiesByName.get(name);
320
    }
321

    
322
    @Override
323
    public EntityRow getWorkspaceEntityByCode(String code) {
324
        if (this.workspaceEntitiesByCode == null) {
325
            this.loadEntities();
326
        }
327
        return this.workspaceEntitiesByCode.get(code);
328
    }
329

    
330
    @Override
331
    public EntityRow getWorkspaceEntity(String entity) {
332
        EntityRow wsentity = this.getWorkspaceEntityByCode(entity);
333
        if( wsentity==null ) {
334
            wsentity = this.getWorkspaceEntityByName(entity);
335
        }
336
        return wsentity;
337
    }
338
    
339
    @Override
340
    public VCSGisEntity getRepositoryEntityByCode(String entityCode) {
341
        if (this.repositoryEntitiesByCode == null) {
342
            reloadRepositoryEntities(null);
343
        }
344
        return this.repositoryEntitiesByCode.get(entityCode);
345
    }
346
    
347
    @Override
348
    public VCSGisEntity getRepositoryEntityByName(String entityName) {
349
        if (this.repositoryEntitiesByCode == null) {
350
            reloadRepositoryEntities(null);
351
        }
352
        for (VCSGisEntity entity : this.repositoryEntitiesByCode.values()) {
353
            if( StringUtils.equalsIgnoreCase(entity.getEntityName(), entityName) ) {
354
                return entity;
355
            }
356
        }
357
        return null;
358
    }
359

    
360
    @Override
361
    public VCSGisEntity getEntity(String entityName) {
362
        VCSGisEntity entity = this.getWorkspaceEntity(entityName);
363
        if(entity == null){
364
            entity = this.getRepositoryEntity(entityName);
365
        }
366
        return entity;
367
    }
368
    
369
    @Override
370
    public VCSGisEntity getRepositoryEntity(String entity) {
371
        VCSGisEntity rentity = this.getRepositoryEntityByCode(entity);
372
        if( rentity==null ) {
373
            rentity = this.getRepositoryEntityByName(entity);
374
        }
375
        return rentity;
376
    }
377
    
378
    public void reloadRepositoryEntities(SimpleTaskStatus status) {
379
        //Esto recarga el map
380
        this.getRepositoryEntities(status);
381
    }
382
    
383

    
384
    public void reloadWorkspaceEntities() {
385
        this.workspaceEntitiesByCode = null;
386
        this.workspaceEntitiesByName = null;
387
    }
388

    
389
    @Override
390
    public void create_table(String name) {
391
        EntityRow entity = this.getWorkspaceEntityByName(name);
392
        if (entity == null) {
393
            throw new IllegalArgumentException("Can't locate informacion of table '" + name + "'.");
394
        }
395
        create_table(entity);
396
    }
397

    
398
    @Override
399
    public void create_table(VCSGisEntity entity) {
400
        if (entity == null) {
401
            throw new IllegalArgumentException("Entity is null.");
402
        }
403
        try {
404
            DataManager dataManager = DALLocator.getDataManager();
405
            JDBCNewStoreParameters addparams = (JDBCNewStoreParameters) this.wsexplorer.getAddParameters(entity.getEntityName());
406
            addparams.setDefaultFeatureType(entity.getFeatureType());
407
            this.wsexplorer.add(DataStore.H2SPATIAL_PROVIDER_NAME, addparams, true);
408

    
409
        } catch (Exception ex) {
410
            throw new RuntimeException("Can't create table '" + entity.getEntityName() + "'.", ex);
411
        }
412

    
413
    }
414

    
415
    @Override
416
    public FeatureStore getFeatureStore(String tableName) {
417
        EntityRow entity = null;
418
        if( !INTERNAL_TABLES.contains(tableName) ) {
419
            entity = this.getWorkspaceEntityByName(tableName);
420
            if (entity == null) {
421
                return null;
422
            }
423
            return getFeatureStore(entity);
424
        }
425
        FeatureStore store = this.storesCache.get(tableName);
426
        if (store != null) {
427
            DisposeUtils.bind(store);
428
            return store;
429
        }
430
        DataManager dataManager = DALLocator.getDataManager();
431
        try {
432
            JDBCStoreParameters params = this.wsexplorer.get(tableName);
433
            store = (FeatureStore) dataManager.openStore(
434
                    DataStore.H2SPATIAL_PROVIDER_NAME,
435
                    params
436
            );
437

    
438
            this.storesCache.put(tableName, store);
439

    
440
            DisposeUtils.bind(store);
441
            return store;
442
        } catch (Exception ex) {
443
            String msg = "can't open store from '" + this.getMessageLabel() + "'.";
444
            throw new RuntimeException(msg, ex);
445
        }
446
    }
447

    
448
    private FeatureStore getFeatureStore(VCSGisEntity entity) {
449
        FeatureStore store = this.storesCache.get(entity.getEntityName());
450
        if (store != null) {
451
            DisposeUtils.bind(store);
452
            return store;
453
        }
454
        DataManager dataManager = DALLocator.getDataManager();
455
        try {
456
            JDBCStoreParameters params = this.wsexplorer.get(entity.getEntityName());
457
            store = (FeatureStore) dataManager.openStore(
458
                    DataStore.H2SPATIAL_PROVIDER_NAME,
459
                    params
460
            );
461

    
462
            StoreProperties.set(store, this, entity.getEntityName());
463

    
464
            this.storesCache.put(entity.getEntityName(), store);
465

    
466
            DisposeUtils.bind(store);
467
            return store;
468
        } catch (Exception ex) {
469
            String msg = "can't open store from '" + this.getMessageLabel() + "'.";
470
            throw new RuntimeException(msg, ex);
471
        }
472
    }
473

    
474
    @Override
475
    public String createUniqueCode() {
476
        return this.codeGenerator.generateCode();
477
    }
478

    
479
    @Override
480
    public String getErrorMessage(int errcode) {
481
        return VCSGisUtils.getErrorMessage(errcode);
482
    }
483

    
484
    @Override
485
    public int addChange(int operation, FeatureStore userStore, Feature feature) {
486
        String entityName = StoreProperties.getEntityName(userStore);
487
        if (StringUtils.isBlank(entityName)) {
488
            return ERR_STORE_NOT_IN_VERSION_CONTROL;
489
        }
490
        if (this.isInStoreIgnoreChanges(userStore)) {
491
            LOGGER.debug("===: ADD_CHANGE: Skip ("+userStore.getName()+")");
492
            return ERR_NO_ERROR;
493
        }
494
        EntityRow entity = this.getWorkspaceEntityByName(entityName);
495
        FeatureStore changesStore = this.getFeatureStore(WorkspaceChangesTable.TABLE_NAME);
496
        try {
497
            changesStore.edit(MODE_PASS_THROUGH);
498
            return addChange(entity, operation, changesStore, feature);
499
        } catch(Exception ex) {
500
            LOGGER.warn("Can't add change (op "+VCSGisUtils.getOperationLabel(operation)+", "+entity.getEntityName()+")", ex);
501
            changesStore.cancelEditingQuietly();
502
            return ERR_CANT_ADD_CHANGE;
503
        } finally {
504
            changesStore.finishEditingQuietly();
505
            DisposeUtils.dispose(changesStore);
506
        }
507
    }
508
    
509
    private int addChange(VCSGisWorkspaceEntity entity, int operation, FeatureStore changesStore, Feature feature) {
510
        try {
511
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, changesStore.createNewFeature());
512
            change.newCode();
513
            change.setEntityCode(entity.getEntityCode());
514
            change.setFeatureCode(feature.getString(entity.getFeatureIdFieldName()));
515
            change.setOperation(operation);
516
            change.setLabel(feature.getString(entity.getFieldForLabel()));
517
            change.setSelected(true);
518
            change.insert(changesStore);
519
            return ERR_OK;
520
        } catch(Exception ex) {
521
            LOGGER.warn("Can't add change (op "+VCSGisUtils.getOperationLabel(operation)+", "+entity.getEntityName()+")", ex);
522
            return ERR_CANT_ADD_CHANGE;
523
        }
524
    }
525
    
526
    private int addDeleteChange(VCSGisWorkspaceEntity entity, FeatureStore changesStore, String featureCode, String label) {
527
        try {
528
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, changesStore.createNewFeature());
529
            change.newCode();
530
            change.setEntityCode(entity.getEntityCode());
531
            change.setFeatureCode(featureCode);
532
            change.setOperation(OP_DELETE);
533
            change.setLabel(label);
534
            change.setSelected(true);
535
            change.insert(changesStore);
536
            return ERR_OK;
537
        } catch(Exception ex) {
538
            LOGGER.warn("Can't add delete change ("+entity.getEntityName()+")", ex);
539
            return ERR_CANT_ADD_CHANGE;
540
        }
541
    }
542

    
543
    @Override
544
    public int addEntity(FeatureType featureType, String name, String description, String fieldForLabel) {
545
        return this.addEntity(featureType, name, description, fieldForLabel, null);
546
    }
547

    
548

    
549
    @Override
550
    public int addEntity(FeatureType featureType, String name, String description, String fieldForLabel, String pkName) {
551
        FeatureStore store = null;
552
        int err = ERR_NO_ERROR;
553
        try {
554
            LOGGER.debug("===: ADD_ENTITY "+this.getCode()+", '"+this.getLabel()+"', "+name);
555
            EditableFeatureType ft = featureType.getCopy().getEditable();
556
            
557
            for (FeatureAttributeDescriptor attr : ft.getPrimaryKey()) {
558
                EditableFeatureAttributeDescriptor editAttr = (EditableFeatureAttributeDescriptor)attr;
559
                editAttr.setIsPrimaryKey(false);
560
                editAttr.setAllowNull(false);
561
                editAttr.setIsIndexed(true);
562
                editAttr.setAllowIndexDuplicateds(false);
563
            }
564

    
565
            EditableFeatureAttributeDescriptor attr = (EditableFeatureAttributeDescriptor)ft.getAttributeDescriptor(FEATURECODE_FIELD_NAME);
566
            if (attr == null) {
567
                err = ERR_ENTITY_NOT_HAS_VCSGISCODE;
568
                ft.add(FEATURECODE_FIELD_NAME, DataTypes.STRING)
569
                        .setSize(40)
570
                        .setIsPrimaryKey(true)
571
                        .setIsIndexed(true)
572
                        .setAllowIndexDuplicateds(false)
573
                        .setLabel("VCSGIS Code");
574
                ft.setHasOID(false);
575
            } else {
576
                if(!attr.isPrimaryKey()){
577
                    attr.setIsPrimaryKey(true);
578
                    ft.setHasOID(false);
579
                }
580
            }
581
            
582
            featureType = ft.getNotEditableCopy();
583
            if (featureType.getAttributeDescriptor(fieldForLabel) == null) {
584
                FeatureAttributeDescriptor[] pk = featureType.getPrimaryKey();
585
                if( pk == null || pk.length<1 ) {
586
                    fieldForLabel = featureType.getAttributeName(0);
587
                } else {
588
                    fieldForLabel = pk[0].getName();
589
                }
590
            }
591
            
592
            err = ERR_CANT_OPEN_ENTITIES;
593
            EntityRow entity = new EntityRow(this);
594
            entity.setEntityName(name);
595
            entity.setDataTableName(DEFAULT_DATA_TABLE);
596
            entity.setFeatureIdFieldName(FEATURECODE_FIELD_NAME);
597
            entity.setGeometryFieldName(featureType.getDefaultGeometryAttributeName());
598
            entity.setDescription(description);
599
            entity.setFieldForLabel(fieldForLabel);
600
            entity.setFeatureTypeAsJson(featureType.toJsonBuilder().toString());
601
            entity.setLocalRevisionCode(null); 
602
            entity.setRepositoryRevisionCode(null); 
603
            entity.setState(STATE_NEW);
604
            entity.insert();
605

    
606
            this.reloadWorkspaceEntities();
607
            err = ERR_CANT_INSERT_CHANGE;
608

    
609
            entity = this.getWorkspaceEntityByName(name);
610
            WorkspaceChangeRow change = new WorkspaceChangeRow(this);
611
            change.setEntityCode(entity.getCode());
612
            change.setFeatureCode(null);
613
            change.setOperation(OP_ADD_ENTITY);
614
            change.setSelected(true);
615
            change.insert();
616

    
617
            this.create_table(entity);
618

    
619
        } catch (VCSGisRuntimeException ex) {
620
            LOGGER.warn("can't add entity '" + name + "'.", ex);
621
            if (store != null) {
622
                store.cancelEditingQuietly();
623
            }
624
            return ex.getErrnum();
625
        } catch (Exception ex) {
626
            LOGGER.warn("can't add entity '" + name + "'.", ex);
627
            if (store != null) {
628
                store.cancelEditingQuietly();
629
            }
630
            return err;
631
        } finally {
632
            DisposeUtils.disposeQuietly(store);
633
        }
634
        return ERR_NO_ERROR;
635
    }
636

    
637
    
638
    @Override
639
    public int addChanges(FeatureStore store, Iterator<Feature> insertedsFeatures, Iterator<Feature> updatedsFeatures, Iterator<FeatureReference> deletedsFeatures) {
640
        String entityName = StoreProperties.getEntityName(store);
641
        if (StringUtils.isBlank(entityName)) {
642
            return ERR_STORE_NOT_IN_VERSION_CONTROL;
643
        }
644
        if (this.isInStoreIgnoreChanges(store)) {
645
            LOGGER.debug("===: ADD_CHANGE: Skip ("+store.getName()+")");
646
            return ERR_NO_ERROR;
647
        }
648
        EntityRow entity = this.getWorkspaceEntityByName(entityName);
649
        if (entity == null) {
650
            return ERR_STORE_NOT_IN_VERSION_CONTROL;
651
        }
652
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
653
        FeatureStore changes_store = null;
654
        int err = ERR_CANT_OPEN_CHANGES;
655
        try {
656
            changes_store = this.getFeatureStore(WorkspaceChangesTable.TABLE_NAME);
657
            err = ERR_CANT_INSERT_CHANGE;
658
            changes_store.edit(FeatureStore.MODE_PASS_THROUGH);
659
            if (insertedsFeatures != null) {
660
                while (insertedsFeatures.hasNext()) {
661
                    Feature f = insertedsFeatures.next();
662
                    if (f == null) {
663
                        continue;
664
                    }
665
                    WorkspaceChangeRow change = new WorkspaceChangeRow(this);
666
                    change.setEntityCode(entity.getCode());
667
                    change.setFeatureCode(f.getString(entity.getFeatureIdFieldName()));
668
                    change.setOperation(OP_INSERT);
669
                    change.setLabel(f.getString(entity.getFieldForLabel()));
670
                    change.setSelected(true);
671
                    change.insert(changes_store);
672
                }
673
            }
674
            if (updatedsFeatures != null) {
675
                while (updatedsFeatures.hasNext()) {
676
                    Feature f = updatedsFeatures.next();
677
                    if (f == null) {
678
                        continue;
679
                    }
680
                    WorkspaceChangeRow change = new WorkspaceChangeRow(this);
681
                    String featureCode = f.getString(entity.getFeatureIdFieldName());
682
                    WorkspaceChangeRow previousChange = changesTable.find(this, changes_store, entity.getCode(), featureCode);
683
                    if(previousChange == null) {
684
                        change.setEntityCode(entity.getCode());
685
                        change.setFeatureCode(f.getString(entity.getFeatureIdFieldName()));
686
                        change.setOperation(OP_UPDATE);
687
                        change.setLabel(f.getString(entity.getFieldForLabel()));
688
                        change.setSelected(true);
689
                        change.insert(changes_store);
690
                    }
691
                }
692
            }
693
            if (deletedsFeatures != null) {
694
                while (deletedsFeatures.hasNext()) {
695
                    FeatureReference fr = deletedsFeatures.next();
696
                    if (fr == null) {
697
                        continue;
698
                    }
699
                    Feature f = fr.getFeatureQuietly();
700
                    if (f == null) {
701
                        continue;
702
                    }
703
                    WorkspaceChangeRow change = new WorkspaceChangeRow(this);
704
                    String featureCode = f.getString(entity.getFeatureIdFieldName());
705
                    WorkspaceChangeRow previousChange = changesTable.find(this, changes_store, entity.getCode(), featureCode);
706
                    if(previousChange == null) {
707
                        change.setEntityCode(entity.getCode());
708
                        change.setFeatureCode(f.getString(entity.getFeatureIdFieldName()));
709
                        change.setOperation(OP_DELETE);
710
                        change.setLabel(f.getString(entity.getFieldForLabel()));
711
                        change.setSelected(true);
712
                        change.insert(changes_store);
713
                    } else {
714
                        switch(previousChange.getOperation()){
715
                            case OP_INSERT:
716
                                previousChange.delete(changes_store);
717
                                break;
718
                            case OP_DELETE:
719
                                LOGGER.warn("Try delete feature already deleted (.'"+previousChange.getRelatedFeature().toJson().toString()+"'");
720
                                break;
721
                            case OP_UPDATE:
722
                                previousChange.setOperation(OP_DELETE);
723
                                previousChange.setSelected(true);
724
                                previousChange.update();
725
                                break;
726
                        }
727
                    }
728
                }
729
            }
730
            changes_store.finishEditing();
731
            err = ERR_NO_ERROR;
732
        } catch (Exception ex) {
733
            this.logger.warn("Can't add changes.", ex);
734
            if (changes_store != null) {
735
                changes_store.cancelEditingQuietly();
736
            }
737
        } finally {
738
            DisposeUtils.disposeQuietly(changes_store);
739
        }
740
        return err;
741
    }
742

    
743
    @Override
744
    public int add(String name, FeatureStore source, String fieldForLabel) {
745
        return this.add(name, source, fieldForLabel, null);
746
    }
747

    
748
    @Override
749
    public int add(String name, FeatureStore source, String fieldForLabel, String pkName) {
750
        FeatureStore target = null;
751
        DisposableFeatureSetIterable features = null;
752
        int errcode = ERR_NO_ERROR;
753
        try {
754
            LOGGER.debug("===: ADD "+this.getCode()+", '"+this.getLabel()+"', "+name);
755
            EntityRow entity = this.getWorkspaceEntityByName(name);
756
            if (entity != null) {
757
                return ERR_ENTITY_ALREADY_EXISTS;
758
            }
759
            FeatureType ft = source.getDefaultFeatureTypeQuietly();
760
            errcode = this.addEntity(ft, name, null, fieldForLabel, pkName);
761
            if (errcode != ERR_NO_ERROR) {
762
                return errcode;
763
            }
764
            errcode = ERR_CANT_OPEN_STORE;
765
            target = this.getFeatureStore(name);
766
            errcode = ERR_CANT_RETRIEVE_SOURCE_FEATURES;
767
            features = source.getFeatureSet().iterable();
768
            errcode = ERR_CANT_INSERT_FEATURES;
769
            target.edit(FeatureStore.MODE_APPEND);
770
            for (Feature feature : features) {
771
                EditableFeature f = target.createNewFeature(feature);
772
                target.insert(f);
773
            }
774
            target.finishEditing();
775
            return ERR_NO_ERROR;
776
        } catch (Exception ex) {
777
            LOGGER.warn("Can't add features to '" + name + "' in '" + this.getMessageLabel() + "'.", ex);
778
            return errcode;
779
        } finally {
780
            DisposeUtils.disposeQuietly(features);
781
            DisposeUtils.disposeQuietly(target);
782
        }
783
    }
784

    
785
    @Override
786
    public VCSGisWorkspaceChanges<VCSGisWorkspaceChange> getLocalChanges() {
787
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
788
        ChangesImpl changes = new ChangesImpl<WorkspaceChangeRow>(changesTable.getByEntityCode(this,null), WorkspaceChangesTable.SELECTED) {
789
            @Override
790
            protected WorkspaceChangeRow createChange(Feature f) {
791
                return new WorkspaceChangeRow(VCSGisWorkspaceImpl.this, f);
792
            }
793

    
794
            @Override
795
            protected void updateChange(FeatureStore store, WorkspaceChangeRow change) {
796
                change.update(store);
797
            }            
798

    
799
        };
800
        return changes;
801
    }
802
    
803
    @Override
804
    public VCSGisWorkspaceChanges<VCSGisWorkspaceChange> getLocalChangesByEntityName(String entityName) {
805
        EntityRow entity = this.getWorkspaceEntityByName(entityName);
806
        return getLocalChangesByEntityCode(entity.getEntityCode());
807
    }
808

    
809
    @Override
810
    public VCSGisWorkspaceChanges<VCSGisWorkspaceChange> getLocalChangesByEntityCode(String entityCode) {
811
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
812
        ChangesImpl changes = new ChangesImpl<WorkspaceChangeRow>(changesTable.getByEntityCode(this,entityCode),WorkspaceChangesTable.SELECTED) {
813
            @Override
814
            protected WorkspaceChangeRow createChange(Feature f) {
815
                return new WorkspaceChangeRow(VCSGisWorkspaceImpl.this, f);
816
            }
817

    
818
            @Override
819
            protected void updateChange(FeatureStore store, WorkspaceChangeRow change) {
820
                change.update(store);
821
            }
822

    
823
        };
824
        return changes;
825
    }
826

    
827
    @Override
828
    public VCSGisRepository getRepository() {
829
        return repository;
830
    }
831

    
832
    @Override
833
    public List<VCSGisEntity> getEntitiesOfRemoteChanges() {
834
        ArrayList<VCSGisEntity> res = new ArrayList<>();
835
        RemoteChangesTable changesTable = new RemoteChangesTable();
836
        DisposableFeatureSetIterable features = changesTable.getGroupedByEntity(this);
837
        EntitiesRepoTable entitiesRepoTable = new EntitiesRepoTable();
838
        for (Feature feature : features) {
839
            VCSGisEntity entity = entitiesRepoTable.getByEntityCode((VCSGisRepositoryLocaldb) this.getRepository(), feature.getString(RemoteChangesTable.COD_ENTITY));
840
            res.add(entity);
841
        }
842
        DisposeUtils.disposeQuietly(features);
843
        return res;
844
    }
845
    
846
    @Override
847
    public VCSGisWorkspaceChanges<VCSGisRepositoryChange> getRemoteChanges() {
848
        return getRemoteChangesByEntity(null);
849
    }
850

    
851
    @Override
852
    public VCSGisWorkspaceChanges<VCSGisRepositoryChange> getRemoteChangesByEntity(String entityName) {
853
        String entityCode;
854
        if(StringUtils.isBlank(entityName)){
855
            entityCode = null;
856
        } else {
857
            VCSGisEntity entity = this.getWorkspaceEntity(entityName);
858
            if(entity == null){
859
                entity = this.getRepositoryEntity(entityName);
860
                if(entity == null){
861
                    return null;
862
                }
863
            }
864
            entityCode = entity.getEntityCode();
865
        }
866
        RemoteChangesTable changesTable = new RemoteChangesTable();
867
        ChangesImpl changes = new ChangesImpl<RemoteChangeRow>(changesTable.getByEntityCode(this,entityCode),RemoteChangesTable.SELECTED) {
868
            @Override
869
            protected RemoteChangeRow createChange(Feature f) {
870
                return new RemoteChangeRow(VCSGisWorkspaceImpl.this, f);
871
            }
872

    
873
            @Override
874
            protected void updateChange(FeatureStore store, RemoteChangeRow change) {
875
                change.update(store);
876
            }
877
            
878
        };
879
        return changes;
880
    }
881

    
882
    private Timestamp now() {
883
        return Timestamp.from(LocalDateTime.now().toInstant(ZoneOffset.UTC));
884
    }
885
  
886
    public boolean prepareCommitRequest(VCSGisCommitRequest request, Timestamp efectivedate, String comment, SimpleTaskStatus status) {
887
        if( status==null ) {
888
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Prepare commit request");
889
            status.setAutoremove(true);
890
            status.add();
891
        }
892
        request.setEfectiveDate(efectivedate);
893
        request.setComment(comment);
894
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
895

    
896
        LOGGER.debug("===: COMMIT: Adding changed local entities");
897
        status.message("Searching changed entities");
898
        // adicionamos las entidades que vamos a actualizar con las revisiones que tenemos.
899
        DisposableFeatureSetIterable changesGroupedByEntity = changesTable.getGroupedByEntity(this);
900
        for (Feature fchange : changesGroupedByEntity) {
901
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
902
            VCSGisEntity localEntity = change.getEntity();
903
            LOGGER.debug("===: COMMIT: add used entity = "+fchange.toJson().toString().replace('\n', ' '));
904
            request.add(request.createEntity(localEntity));
905
        }
906
        changesGroupedByEntity.dispose();
907

    
908
        LOGGER.debug("===: COMMIT: Mark new local entities");
909
        status.message("Searching new entities");
910
        // Marcamos como nuevas las entidades que se han dado de alta.
911
        DisposableFeatureSetIterable changesOfAddEntities = changesTable.getByOperation(this, OP_ADD_ENTITY);
912
        for (Feature fchange : changesOfAddEntities) {
913
            WorkspaceChangeRow change = new WorkspaceChangeRow(this, fchange);
914
            request.markAsNew(change.getEntity());
915
        }
916
        changesOfAddEntities.dispose();
917

    
918
        LOGGER.debug("===: COMMIT: Adding data");
919
        status.message("Searching changed data");
920
        // adicionamos los datos
921
        boolean useSeleccion = true;
922
        DisposableFeatureSetIterable changes = changesTable.getSelectedsWithoutAddEntity(this);
923
        if (changes == null) {
924
            changes = changesTable.getAll(this);
925
            useSeleccion = false;
926
        }
927
        request.add(new DisposableIterableAdapter(
928
                changes, 
929
                new DisposableIterableAdapter.ItemConverter<Feature, VCSGisChange>() {
930
                    @Override
931
                    public VCSGisChange convert(Feature f) {
932
                        return new WorkspaceChangeRow(VCSGisWorkspaceImpl.this, f);
933
                    }
934
                }
935
            )
936
        );
937
        return useSeleccion;
938
    }
939
    
940
    @Override
941
    public int commit() {
942
        return commit(now(),null, null);
943
    }
944
  
945
    @Override
946
    @SuppressWarnings("Convert2Lambda")
947
    public int commit(Timestamp efectivedate, String comment, SimpleTaskStatus status) {
948
        VCSGisCommitRequest request = null;
949
        if( status==null ) {
950
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Commit");
951
            status.setAutoremove(true);
952
            status.add();
953
        }
954
        try {
955
            LOGGER.debug("===: COMMIT "+this.getCode()+", "+this.getLabel());
956
            EntitiesTable entitiesTable = new EntitiesTable();
957
            WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
958
            
959
            status.message("Preparing commit");
960
            reloadRepositoryEntities(status);
961
            request = this.repository.createCommitRequest();
962

    
963
            boolean useSeleccion = this.prepareCommitRequest(request, efectivedate, comment, status);
964
            
965
            LOGGER.debug("===: COMMIT: Do execute request");
966
            status.message("Executing commit request");
967
            if( request.execute()!=ERR_NO_ERROR ) {
968
                status.message("Can't commit changes (error "+request.getLastErrorCode()+")");
969
                status.abort();
970
                return request.getLastErrorCode();
971
            }
972

    
973
            LOGGER.debug("===: COMMIT: update local entities table");
974
            status.message("Updating local metadata");
975
            FeatureStore store = null;
976
            try {
977
                store = this.getFeatureStore(EntitiesTable.TABLE_NAME);
978
                store.edit(FeatureStore.MODE_FULLEDIT);
979
                for (VCSGisEntity rentity : request.getChangedLocalEntities()) {
980
                    EntityRow entityRow = entitiesTable.getByEntityName(this, rentity.getEntityName());
981
                    if (entityRow != null) {
982
                        entityRow.copyfrom(rentity);
983
                        entityRow.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
984
                        entityRow.update(store);
985
                    }
986
                }
987
                store.finishEditing();
988
                reloadWorkspaceEntities();
989
            } finally {
990
                DisposeUtils.disposeQuietly(store);
991
                store = null;
992
            }
993

    
994
            LOGGER.debug("===: COMMIT: clean local changes");
995
            status.message("Removing local list of changes");
996
            if (useSeleccion) {
997
                changesTable.deleteSelecteds(this);
998
            } else {
999
                changesTable.deleteAll(this);
1000
            }
1001
            status.message("Commit completed");
1002
            status.terminate();
1003
            return ERR_NO_ERROR;
1004
        } catch (Exception ex) {
1005
            LOGGER.warn("Can't commit changes.", ex);
1006
            status.message("Can't commit changes");
1007
            status.abort();
1008
            return ERR_CANT_COMMIT;
1009
        } finally {
1010
            DisposeUtils.disposeQuietly(request);
1011
        }
1012
    }
1013

    
1014
    @Override
1015
    public int checkout(String tableName) {
1016
        return checkout(tableName, null);
1017
    }
1018
    
1019
    @Override
1020
    public int checkout(String tableName, SimpleTaskStatus status) {
1021
        FeatureStore target = null;
1022
        int errcode = ERR_OK;
1023
        VCSGisCheckoutRequest request = null;
1024
        if( status==null ) {
1025
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Checkout");
1026
            status.setAutoremove(true);
1027
            status.add();
1028
        }
1029
        try {
1030
            LOGGER.debug("===: CHECKOUT "+this.getCode()+", '"+this.getLabel()+"', "+tableName);
1031
            status.message("Preparing checkout");
1032
            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
1033
            if(lentity != null){
1034
                status.message("Table "+tableName+" already exists");
1035
                status.abort();
1036
                return ERR_ENTITY_ALREADY_EXISTS;
1037
            }
1038
            reloadRepositoryEntities(status);
1039
            request = this.repository.createCheckoutRequest(tableName);
1040
            request.setEfectiveDate((Timestamp)null);
1041
            request.setRevisionCode(null);
1042

    
1043
            status.message("Executing checkout request for "+tableName);
1044
            if( request.execute()!=ERR_OK ) {
1045
                status.message("Can't checkout "+tableName+" (error "+request.getLastErrorCode()+")");
1046
                status.abort();
1047
                return request.getLastErrorCode();
1048
            }
1049
            status.message("Updating "+tableName+" metadata");
1050
            VCSGisEntity rentity = request.getEntity();            
1051
            lentity = new EntityRow(this);
1052
            rentity.copyto(lentity);
1053
            lentity.insert();
1054
            LOGGER.debug("===: CHECKOUT "+this.getCode()+", '"+this.getLabel()+"', "+tableName+", rev."+rentity.getRepositoryRevisionCode());
1055

    
1056
            this.reloadWorkspaceEntities();
1057

    
1058
            status.message("Creating table "+tableName);
1059
            this.create_table(lentity);
1060

    
1061
            status.message("Adding features in "+tableName);
1062
            errcode = ERR_CANT_OPEN_STORE;
1063
            target = this.getFeatureStore(tableName);
1064
            this.addStoreIgnoreChanges(target);
1065
            DisposableIterable<VCSGisRepositoryData> data = request.getData();
1066
            long sz = ContainerUtils.size64(data);
1067
            status.setRangeOfValues(0, sz);
1068
            status.setCurValue(0);
1069
            errcode = ERR_CANT_INSERT_FEATURES;
1070
            target.edit(FeatureStore.MODE_APPEND);
1071
            for (VCSGisRepositoryData d : data) {
1072
                EditableFeature f = target.createNewFeature(d.getDataAsJson());
1073
                target.insert(f);
1074
                status.incrementCurrentValue();
1075
            }
1076
            target.finishEditing();
1077

    
1078
            status.message("Updating "+tableName+" metadata");
1079
            lentity.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
1080
            lentity.update();
1081
            this.reloadWorkspaceEntities();
1082

    
1083
            request.dispose();
1084

    
1085
            status.message("Checkout completed");
1086
            status.terminate();
1087
            return ERR_NO_ERROR;
1088
        } catch (Exception ex) {
1089
            LOGGER.warn("Can't checkout.", ex);
1090
            status.message("Can't checkout");
1091
            status.abort();
1092
            return errcode;
1093
        } finally {
1094
            DisposeUtils.disposeQuietly(request);
1095
            if(target != null) {
1096
                this.removeStoreIgnoreChanges(target);
1097
            }
1098
            DisposeUtils.disposeQuietly(target);
1099
        }
1100
    }
1101

    
1102
    @Override
1103
    public int updateEntities() {
1104
        return this.updateEntities(null);
1105
    }
1106

    
1107
    @Override
1108
    public int updateEntities(SimpleTaskStatus status) {
1109
        LOGGER.debug("===: UPDATE_ENTITIES "+this.getCode()+", '"+this.getLabel()+"'");
1110
        FeatureStore store = null;
1111
        EntitiesTable entitiesTable = new EntitiesTable();
1112
        if( status==null ) {
1113
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Update metadata tables");
1114
            status.setAutoremove(true);
1115
            status.add();
1116
        }
1117
        try {
1118
            status.message("Preparing update metadata tables");
1119
            store = this.getFeatureStore(EntitiesTable.TABLE_NAME);
1120
            store.edit(FeatureStore.MODE_PASS_THROUGH);
1121
            for (VCSGisEntity rentity : this.getRepositoryEntities(status)) {
1122
                EntityRow entityRow = entitiesTable.getByEntityName(this, rentity.getEntityName());
1123
                if (entityRow != null) {
1124
                    rentity.copyto(entityRow);
1125
                    entityRow.update(store);
1126
                }
1127
            }
1128
            reloadWorkspaceEntities();
1129
            store.finishEditingQuietly();
1130
            status.message("Update metadata tables completed");
1131
            status.terminate();
1132
            return ERR_OK;
1133
        } catch (Exception ex) {
1134
            LOGGER.warn("Can't update metadata tables.", ex);
1135
            status.message("Can't update metadata tables");
1136
            status.abort();
1137
            return ERR_CANT_UPDATE_ENTITIES;
1138
        } finally {
1139
            DisposeUtils.disposeQuietly(store);
1140
            store = null;
1141
        }
1142
    }
1143

    
1144
    @Override
1145
    public int updatePrepare(String tableName) {
1146
        return updatePrepare(tableName, null);
1147
    }
1148

    
1149
    @Override
1150
    public int updatePrepare(String tableName, SimpleTaskStatus status) {
1151
        LOGGER.debug("===: UPDATE_PREPARE: "+tableName+" WS "+this.getCode()+", '"+this.getLabel()+"'");
1152
        if( status==null ) {
1153
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Update-prepare "+tableName);
1154
            status.setAutoremove(true);
1155
            status.add();
1156
        }
1157

    
1158
        FeatureStore target = null;
1159
        VCSGisUpdateRequest request = null;
1160
        DisposableIterable<VCSGisRepositoryData> remoteChanges = null;
1161
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1162
        try {
1163
            status.message("Preparing update-prepare");
1164
            reloadRepositoryEntities(status);
1165
            request = this.repository.createUpdateRequest(tableName);
1166
            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
1167
            if(lentity != null){
1168
                request.setLocalRevisionCode(lentity.getLocalRevisionCode());
1169
            }
1170

    
1171
            status.message("Executing update-prepare request");
1172
            if( request.execute()!=ERR_OK ) {
1173
                status.message("Can't update-prepare "+tableName+" (error "+request.getLastErrorCode()+")");
1174
                status.abort();
1175
                return request.getLastErrorCode();
1176
            }
1177
            status.message("Updating "+tableName+" metadata");
1178
            LOGGER.debug("===: UPDATE_PREPARE: "+tableName+" request code "+request.getCode());
1179
            VCSGisEntity rentity = request.getEntity();
1180
            if(lentity == null){
1181
                lentity = new EntityRow(this);
1182
                lentity.copyfrom(rentity);
1183
                lentity.setLocalRevisionCode(null);
1184
            } else {
1185
                lentity.copyfrom(rentity);
1186
                lentity.update();
1187
            }
1188
            this.reloadWorkspaceEntities();
1189
            String entityCode = lentity.getCode();
1190
            LOGGER.debug("===: UPDATE_PREPARE: "+tableName+" entity code "+entityCode+", repo rev. "+lentity.getRepositoryRevisionCode()+", local rev. "+lentity.getLocalRevisionCode());            
1191

    
1192
            status.message("Preparing remote changes container");
1193
            target = this.getFeatureStore(RemoteChangesTable.TABLE_NAME);
1194
            target.edit(MODE_PASS_THROUGH);
1195

    
1196
            status.message("Deleting previous temporary remote changes");
1197
            LOGGER.debug("===: UPDATE_PREPARE: Delete updates table");
1198
            target.delete("\""+COD_ENTITY+"\"='"+entityCode+"'");
1199

    
1200
            remoteChanges = request.getData();
1201
            long sz = ContainerUtils.size64(remoteChanges);
1202
            status.setRangeOfValues(0, sz);
1203
            status.setCurValue(0);
1204

    
1205
            LOGGER.debug("===: UPDATE_PREPARE: Inserting updates");
1206
            for (VCSGisRepositoryData remoteChange : remoteChanges) {
1207
                RemoteChangeRow remoteChangeRow = new RemoteChangeRow(this);
1208
                LOGGER.debug("===: UPDATE_PREPARE: insert "+remoteChange.getFeatureRelatedCode()+", "+remoteChange.getOperation()+", "+remoteChange.getData());
1209
                remoteChangeRow.setCode(remoteChange.getFeatureRelatedCode());
1210
                remoteChangeRow.setData(remoteChange.getData());
1211
                remoteChangeRow.setEntityCode(remoteChange.getEntityCode());
1212
                remoteChangeRow.setDataCode(remoteChange.getFeatureRelatedCode());
1213
                remoteChangeRow.setOperation(remoteChange.getOperation());
1214
                remoteChangeRow.setRevisionCode(remoteChange.getRevisionCode());
1215
                remoteChangeRow.setRevisionNumber(remoteChange.getRevisionNumber());
1216

    
1217
                LOGGER.debug("===: UPDATE_PREPARE: row code = "+remoteChangeRow.getRelatedFeatureCode());
1218
                LOGGER.debug("===: UPDATE_PREPARE: row state = "+lentity.getState()+", "+lentity.getStateLabel());
1219
                LOGGER.debug("===: UPDATE_PREPARE: row operation = "+remoteChangeRow.getOperation()+", "+remoteChangeRow.getOperationLabel());
1220
                switch (lentity.getState()) {
1221
                    case STATE_OUTDATED:
1222
                    case STATE_UNMODIFIED: 
1223
                        remoteChangeRow.setSelected(true);
1224
                        break;
1225
                    case STATE_NEW:
1226
                    case STATE_OUTDATED_AND_MODIFIED:
1227
                    case STATE_MODIFIED: 
1228
                        WorkspaceChangeRow change = changesTable.getByEntityAndDataCode(this,
1229
                                entityCode,
1230
                                remoteChangeRow.getRelatedFeatureCode()
1231
                        );
1232
                        if( change==null ) {
1233
                            LOGGER.debug("===: UPDATE_PREPARE: no local modificacion, update local data");
1234
                            // Solo actualizamos si no ha sido modificado localmente.
1235
                            remoteChangeRow.setSelected(true);
1236
                        } else {
1237
                            LOGGER.debug("===: UPDATE_PREPARE: not update. Local data is modified. "+change.getData().replace('\n', ' '));
1238
                            remoteChangeRow.setSelected(false);
1239
                        }
1240
                        break;
1241
                }
1242
                remoteChangeRow.insert(target);
1243
                status.incrementCurrentValue();
1244
            }
1245
            LOGGER.debug("===: UPDATE_PREPARE: finish inserting updates");
1246
            target.finishEditing();
1247
            
1248
            status.message("Update-prepare completed");
1249
            status.terminate();
1250
            return ERR_OK;
1251
        } catch (Exception ex) {
1252
            LOGGER.warn("Can't prepare update.", ex);
1253
            status.message("Can't prepare update");
1254
            status.abort();
1255
            if( target!=null ) {
1256
                target.cancelEditingQuietly();
1257
            }
1258
            return ERR_CANT_PREPARE_UPDATE;
1259
        } finally {
1260
            DisposeUtils.disposeQuietly(remoteChanges);
1261
            DisposeUtils.disposeQuietly(request);
1262
            DisposeUtils.disposeQuietly(target);
1263
        }
1264
    
1265
    }
1266

    
1267
    @Override
1268
    public int updateClean(String entityCode) {
1269
        return updateClean(entityCode, null);
1270
    }
1271
    
1272
    @Override
1273
    public int updateClean(String entityCode, SimpleTaskStatus status) {
1274
        VCSGisEntity entity = this.getEntity(entityCode);
1275
        if( entity == null ) {
1276
            return ERR_ENTITY_NOT_EXISTS;
1277
        }
1278
        if( status==null ) {
1279
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
1280
                    "Update-clean "+entity.getEntityName()
1281
            );
1282
            status.setAutoremove(true);
1283
            status.add();
1284
        }
1285
        try {
1286
            status.message("Deleting temporary remote changes ("+entity.getEntityName()+")");
1287
            RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
1288
            remoteChangesTable.delete(this, entityCode);
1289
            status.message("Delete temporary remote changes completed");
1290
            status.terminate();
1291
            return ERR_OK;
1292
        } catch (Exception ex) {
1293
            LOGGER.warn("Can't deleting temporary remote changes of "+entity.getEntityName()+".", ex);
1294
            status.message("Can't deleting temporary remote changes of "+entity.getEntityName()+".");
1295
            status.abort();
1296
            return ERR_CANT_UPDATE_CLEAN;
1297
        }
1298
            
1299
    }
1300

    
1301
    @Override
1302
    public int update(String tableName) {
1303
        return this.update(tableName, true, true, null);
1304
    }
1305
    
1306
    @Override
1307
    public int update(String tableName, SimpleTaskStatus status) {
1308
        return this.update(tableName, false, false, status);
1309
    }
1310

    
1311
    @Override
1312
    public int merge(String tableName) {
1313
        return this.update(tableName, false, true, null);
1314
    }
1315

    
1316
    @Override
1317
    public int merge(String tableName, SimpleTaskStatus status) {
1318
        return this.update(tableName, false, true, status);
1319
    }
1320

    
1321
    public int update(String tableName, boolean prepare, boolean merge, SimpleTaskStatus status) {
1322
        int errcode = ERR_NO_ERROR;
1323
        if( status==null ) {
1324
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
1325
                    "Update "+tableName
1326
            );
1327
            status.setAutoremove(true);
1328
            status.add();
1329
        }
1330
        if( prepare ) {
1331
            errcode = this.updatePrepare(tableName, status);
1332
            if (errcode != ERR_OK) {
1333
                return errcode;
1334
            }
1335
        }
1336
        LOGGER.debug("===: UPDATE "+this.getCode()+", '"+this.getLabel()+"', "+tableName);
1337
        RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
1338

    
1339
        EditableFeature ef;
1340
        FeatureStore target = null;
1341
        DisposableFeatureSetIterable features = null;
1342
        FeatureStore changesStore = null;
1343
        try {
1344
            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
1345
            if(lentity == null){
1346
                VCSGisEntity rentity = this.getRepositoryEntityByName(tableName);
1347
                lentity = new EntityRow(this);
1348
                lentity.copyfrom(rentity);
1349
                lentity.setLocalRevisionCode(null);
1350
            }
1351
            if( !merge ){
1352
                status.message("Checking the need to merge");
1353
                if(remoteChangesTable.updateNeedMerge(this, lentity.getEntityCode())){
1354
                    status.message("Can't update without merge.");
1355
                    status.abort();
1356
                    return ERR_UPDATE_NEED_MERGE;
1357
                }
1358
            }
1359
            String dataCodeFieldName = lentity.getFeatureIdFieldName();
1360
            status.message("Searching remote changes ("+lentity.getEntityName()+")");
1361
            
1362
            try {
1363
                target = this.getFeatureStore(lentity);
1364
            } catch (Exception e){
1365
                LOGGER.warn("Can't get feature store from '"+tableName+"'", e);
1366
            }
1367
            if(target == null) {
1368
                this.create_table(lentity);
1369
                target = this.getFeatureStore(lentity);
1370
            }
1371
            
1372
            features = remoteChangesTable.getSelectedsByEntityCodeAsIterator(this,lentity.getCode());
1373
            long sz = ContainerUtils.size64(features);
1374
            status.setRangeOfValues(0, sz);
1375
            status.setCurValue(0);
1376

    
1377
            if(!features.isEmpty()){
1378
                target.edit(MODE_PASS_THROUGH);
1379
                this.addStoreIgnoreChanges(target);
1380
                status.message("Updating table ("+lentity.getEntityName()+")");
1381
                FeatureType type = target.getDefaultFeatureTypeQuietly();
1382
                
1383
                ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
1384
                ExpressionBuilder builder = expManager.createExpressionBuilder();
1385
                
1386
                for (Feature feature : features) {
1387
                    RemoteChangeRow remoteChangeRow = new RemoteChangeRow(this, feature);
1388
                    switch (remoteChangeRow.getOperation()) {
1389
                        case OP_INSERT:
1390
                            LOGGER.debug("===: UPDATE: insert");
1391
                            ef = target.createNewFeature(remoteChangeRow.getDataAsJson());
1392
                            target.insert(ef);
1393
                            break;
1394
                        case OP_UPDATE:
1395
                            LOGGER.debug("===: UPDATE: update");                            
1396
                            JsonObject dataJson = remoteChangeRow.getDataAsJson();
1397
                            builder.set(null);
1398
                            for (FeatureAttributeDescriptor attr : type.getPrimaryKey()) {
1399
                                builder.and(
1400
                                        builder.eq(
1401
                                                builder.column(attr.getName()), 
1402
                                                builder.constant(
1403
                                                        Json.toObject(dataJson.get(attr.getName()))
1404
                                                )
1405
                                        )
1406
                                );
1407
                            }
1408
                            Feature f = target.findFirst(builder.toString());
1409
                            if(f==null){
1410
                                throw new NullPointerException("Can't update null feature ("+builder.toString()+").");
1411
                            }
1412
                            ef = f.getEditable();
1413
//                          ef = target.createNewFeature(false);
1414
//                          ef.setUpdatable(true);
1415
                            ef.copyFrom(dataJson);
1416
                            target.update(ef);
1417
                            break;
1418

    
1419
                        case OP_DELETE:
1420
                            LOGGER.debug("===: UPDATE: delete");
1421
                            target.delete("\"" + dataCodeFieldName + "\"='" + remoteChangeRow.getRelatedFeatureCode()+ "'");
1422
                            break;
1423
                    }
1424
                    status.incrementCurrentValue();
1425
                }
1426
                target.finishEditing();
1427
            }
1428

    
1429
            if(merge){
1430
                status.message("Searching local changes to merge ("+lentity.getEntityName()+")");
1431
                DisposeUtils.disposeQuietly(features);
1432
                features = remoteChangesTable.getNotSelectedsByEntityCodeAsIterator(this,lentity.getCode());
1433
                sz = ContainerUtils.size64(features);
1434
                status.setRangeOfValues(0, sz);
1435
                status.setCurValue(0);
1436

    
1437
                if(!features.isEmpty()){
1438
                    //We edit the changesStore because we will need local changes 
1439
                    changesStore = this.getFeatureStore(WorkspaceChangesTable.TABLE_NAME);
1440
                    changesStore.edit(MODE_PASS_THROUGH);
1441

    
1442
                    //We edit the target store because perhaps we will need update some feature (in case OP_DELETE)
1443
                    target.edit(MODE_PASS_THROUGH);
1444
                    this.addStoreIgnoreChanges(target);
1445

    
1446
                    status.message("Adding to local changes ("+lentity.getEntityName()+")");
1447
                    for (Feature feature : features) {
1448
                        RemoteChangeRow remoteChangeRow = new RemoteChangeRow(this, feature);
1449
                        Feature f = target.findFirst("\""+lentity.getFeatureIdFieldName()+"\" = '"+remoteChangeRow.getRelatedFeatureCode()+"'");
1450
                        switch (remoteChangeRow.getOperation()) {
1451
                            case OP_INSERT:
1452
                                LOGGER.debug("===: UPDATE: insert");
1453
                                if(f==null){
1454
                                    this.addDeleteChange(lentity, changesStore, remoteChangeRow.getRelatedFeatureCode(), null);
1455
                                } else {
1456
                                    this.addChange(lentity, OP_UPDATE, changesStore, f);
1457
                                }
1458
                                break;
1459

    
1460
                            case OP_UPDATE:
1461
                                LOGGER.debug("===: UPDATE: update");                            
1462
                                if(f==null){
1463
                                    this.addDeleteChange(lentity, changesStore, remoteChangeRow.getRelatedFeatureCode(), null);
1464
                                } else {
1465
                                    this.addChange(lentity, OP_UPDATE, changesStore, f);
1466
                                }
1467
                                break;
1468
                            case OP_DELETE:
1469
                                LOGGER.debug("===: UPDATE: delete");
1470
                                if(f!=null){
1471
                                    //TODO: delete de la f y un insert de una nueva
1472
                                    target.delete("\"" + dataCodeFieldName + "\"='" + remoteChangeRow.getRelatedFeatureCode()+ "'");
1473

    
1474
                                    ef = target.createNewFeature(f);
1475
                                    ef.setString(lentity.getFeatureIdFieldName(), this.createUniqueCode());
1476

    
1477
                                    target.insert(ef);
1478
                                    this.addChange(lentity, OP_INSERT, changesStore, ef);
1479

    
1480
                                }
1481
                                break;
1482
                        }
1483
                        status.incrementCurrentValue();
1484
                    }
1485
                    changesStore.finishEditing();
1486
                    target.finishEditing();
1487
                }
1488
            }
1489
            remoteChangesTable.delete(this, lentity.getEntityCode());
1490
            status.message("Updating metadata tables");
1491
            status.terminate();
1492
            if(lentity.getLocalRevisionCode() == null){
1493
                lentity.setLocalRevisionCode(lentity.getRepositoryRevisionCode());
1494
                lentity.insert();
1495
            } else {
1496
                lentity.setLocalRevisionCode(lentity.getRepositoryRevisionCode());
1497
                lentity.update();
1498
            }
1499
            reloadWorkspaceEntities();
1500
            
1501
            status.message("Update completed");
1502
            status.terminate();
1503
            return ERR_OK;
1504
        } catch (Exception ex) {
1505
            LOGGER.warn("Can't update.", ex);
1506
            status.message("Can't update");
1507
            status.abort();
1508
            if(target != null){
1509
                target.cancelEditingQuietly();
1510
            }
1511
            if(changesStore != null){
1512
                changesStore.cancelEditingQuietly();
1513
            }
1514
            return ERR_CANT_UPDATE;
1515
        } finally {
1516
            this.removeStoreIgnoreChanges(target);
1517
            DisposeUtils.disposeQuietly(features);
1518
            DisposeUtils.disposeQuietly(target);
1519
            DisposeUtils.disposeQuietly(changesStore);
1520
        }
1521
    }
1522

    
1523
    @Override
1524
    public JDBCServerExplorer getExplorer() {
1525
        return this.wsexplorer;
1526
    }
1527
    
1528
    @Override
1529
    public int log(String tableName, int maxRevisions, int operation, SimpleTaskStatus status){
1530
        
1531
        
1532
        FeatureStore target = null;
1533
        int errcode = ERR_OK;
1534
        VCSGisLogRequest request = null;
1535
        if( status==null ) {
1536
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
1537
                    "Log "+tableName
1538
            );
1539
            status.setAutoremove(true);
1540
            status.add();
1541
        }
1542
        try {
1543
            LOGGER.debug("===: LOG "+this.getCode()+", '"+this.getLabel()+"', "+tableName);
1544
            reloadRepositoryEntities(status);
1545

    
1546
            //TODO calcular las revisiones que tengo para excluirlas
1547
            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
1548
            if(lentity == null){
1549
                status.message("Can't find table '"+tableName+"'");
1550
                status.abort();
1551
                return ERR_ENTITY_NOT_EXISTS;
1552
            }
1553
            
1554
            
1555
            LocalRevisionsTable localRevisionsTable = new LocalRevisionsTable();
1556
            GetItemWithSizeAndIterator64<Feature> lrevisions = localRevisionsTable.getAllRevisions(this, lentity.getEntityCode());
1557
            //Asumimos que lrevisions esta ordenado ascendentemente por numero de revision
1558
//            Long prevRevNumber = null;
1559
            Long minRevision = null;
1560
            Long maxRevision = null;
1561
            for (Feature lrevision : lrevisions) {
1562
                LocalRevisionRow x = new LocalRevisionRow(this, lrevision);
1563
                Long revNumber = x.getNumber();
1564
                //Asumimos que las revisiones que tenemos son consecutivas
1565
//                if(prevRevNumber != null && revNumber != prevRevNumber+1){ //Salto
1566
                    //Borrar la tabla completamente ???
1567
//                    target = this.getFeatureStore(LocalRevisionsTable.TABLE_NAME);
1568
//                    target.edit(MODE_PASS_THROUGH);
1569
//                    target.delete
1570
//                }
1571
                if(minRevision == null){
1572
                    minRevision = revNumber;
1573
                }
1574
                maxRevision = revNumber;
1575
            }
1576
            
1577
            status.message("Executing log request");
1578
            request = this.repository.createLogRequest(tableName);
1579
            if(minRevision != null && maxRevision != null){
1580
                request.setExcludeRevisionsRange(Range.between(minRevision, maxRevision));
1581
            }
1582
            request.setOperation(operation);
1583
            request.setMaxRevisions(maxRevisions);
1584
            
1585
            if( request.execute()!=ERR_OK ) {
1586
                status.message("Can't retriev history of "+tableName+" (error "+request.getLastErrorCode()+")");
1587
                status.abort();
1588
                return request.getLastErrorCode();
1589
            }
1590

    
1591
            status.message("Deleting previous local revision information");
1592
            errcode = ERR_CANT_OPEN_STORE;
1593
            target = this.getFeatureStore(LocalRevisionsTable.TABLE_NAME);
1594
            errcode = ERR_CANT_RETRIEVE_SOURCE_FEATURES;
1595
            DisposableIterable<VCSGisRevision> revisions = request.getRevisions();
1596
            status.message("Adding to local revisions");
1597
            long sz = ContainerUtils.size64(revisions);
1598
            status.setRangeOfValues(0, sz);
1599
            status.setCurValue(0);
1600
            
1601
            errcode = ERR_CANT_INSERT_FEATURES;
1602
            target.edit(FeatureStore.MODE_PASS_THROUGH);
1603
            for (VCSGisRevision revision : revisions) {
1604
                if(operation == VCSGisLogRequest.LOG_OP_LAST && revision.getNumber()!=maxRevision+1){
1605
                    //Borrar todo el target ???
1606
                }
1607
                EditableFeature f = target.createNewFeature();
1608
                LocalRevisionRow row = new LocalRevisionRow(this, f);
1609
                row.copyFrom(revision);
1610
                row.insert(target);
1611
                status.incrementCurrentValue();
1612
            }
1613
            target.finishEditing();
1614
            status.message("Log completed");
1615
            status.terminate();
1616
            return ERR_OK;
1617
        } catch (Exception ex) {
1618
            LOGGER.warn("Can't retrieve history.", ex);
1619
            status.message("Can't retrieve history");
1620
            status.abort();
1621
            return errcode;
1622
        } finally {
1623
            DisposeUtils.disposeQuietly(request);
1624
            if(target != null) {
1625
                this.removeStoreIgnoreChanges(target);
1626
            }
1627
            DisposeUtils.disposeQuietly(target);
1628
        }
1629
    }
1630

    
1631
    @Override
1632
    public List<VCSGisWorkspaceRevision> getRemoteRevisions(String tableName) {
1633
//        LocalRevisionsTable table = new LocalRevisionsTable();
1634
//        features = table.getAllRevisions(this, tableName);
1635
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1636
    }
1637

    
1638
    @Override
1639
    public List<VCSGisEntity> getRepositoryEntities() {
1640
        return this.getRepositoryEntities(null);
1641
    }
1642
    
1643
    @Override
1644
    public List<VCSGisEntity> getRepositoryEntities(SimpleTaskStatus status) {
1645
        if( status==null ) {
1646
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Repository tables");
1647
            status.setAutoremove(true);
1648
            status.add();
1649
        }
1650
        try {
1651
            status.message("Getting repository table metadata");
1652
            VCSGisEntitiesRequest request = this.getRepository().createEntitiesRequest();
1653
            request.execute();
1654
            List<VCSGisEntity> entities = request.getRepositoryEntities();
1655
            request.dispose();
1656

    
1657
            Map<String, VCSGisEntity> tmp = new HashMap<>();
1658
            entities.forEach(entity -> {
1659
                tmp.put(entity.getEntityCode(), entity);
1660
            });
1661
            this.repositoryEntitiesByCode = tmp;
1662

    
1663

    
1664
            status.message("Repository tables metadata update completed");
1665
            status.terminate();
1666
            return entities;
1667
        } catch (Exception ex) {
1668
            LOGGER.warn("Can't get repository tables metadata.", ex);
1669
            status.message("Can't get repository tables metadata");
1670
            status.abort();
1671
            return null;
1672
        }
1673
            
1674
    }
1675

    
1676
    @Override
1677
    public boolean updateNeedMerge(String entityName) {
1678
        RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
1679
        
1680
        VCSGisEntity entity = this.getWorkspaceEntity(entityName);
1681
        if(entity == null){
1682
            entity = this.getRepositoryEntity(entityName);
1683
        }
1684
        
1685
        return remoteChangesTable.updateNeedMerge(this, entity.getEntityCode());
1686
    }
1687

    
1688
}