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

History | View | Annotate | Download (150 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 currentUser;
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.currentUser = 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.currentUser = 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.currentUser);
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.currentUser);
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
    private void updateUsersFromRepository(SimpleTaskStatus status) {
1768
        FeatureStore usersStore = null;
1769
        VCSGisUsersRequest request = null;
1770
        try {
1771
            request = this.getRepository().createUsersRequest();
1772
            request.setAuthenticationToken(this.authenticationToken);
1773
            request.setUserCode(this.currentUser);
1774

    
1775
            status.message("Executing users request");
1776
            if ( execute(request) != ERR_OK) {
1777
                status.message("Can't get users (error " + request.getLastErrorCode() + ")");
1778
                return;
1779
            }
1780
            status.message("Updating users information");
1781
            usersStore = this.openFeatureStore(UsersTable.TABLE_NAME);
1782
            usersStore.edit(FeatureStore.MODE_PASS_THROUGH);
1783
            usersStore.delete("TRUE");
1784
            for (VCSGisUser user : request.getUsers()) {
1785
                UsersTable.UserRow row = new UsersTable.UserRow(this);
1786
                row.copyFrom(user);
1787
                row.insert(usersStore);
1788
            }
1789
            usersStore.finishEditing();
1790
            
1791
        } catch(Exception ex) {
1792
            LOGGER.warn("Can't update users.", ex);
1793
            status.message("Can't update users");
1794
            FeatureStore.cancelEditingQuietly(usersStore);
1795
        } finally {
1796
            DisposeUtils.disposeQuietly(request);
1797
            DisposeUtils.disposeQuietly(usersStore);
1798
        }     
1799
    }
1800
    
1801
    private void updateTopologyPlansFromRepository(SimpleTaskStatus status) {
1802
        FeatureStore topologyPlanStore = null;
1803
        VCSGisTopologyPlansRequest request = null;
1804
        try {
1805
            request = this.getRepository().createTopologyPlansRequest();
1806
            request.setAuthenticationToken(this.authenticationToken);
1807
            request.setUserCode(this.currentUser);
1808

    
1809
            status.message("Executing topology plans request");
1810
            if ( execute(request) != ERR_OK) {
1811
                status.message("Can't get topology plans (error " + request.getLastErrorCode() + ")");
1812
                return;
1813
            }
1814
            status.message("Updating topology plans information");
1815
            topologyPlanStore = this.openFeatureStore(TopologyplanTable.TABLE_NAME);
1816
            topologyPlanStore.edit(FeatureStore.MODE_PASS_THROUGH);
1817
            topologyPlanStore.delete("TRUE");
1818
            for (VCSGisTopologyPlan topologyPlan : request.getTopologyPlans()) {
1819
                TopologyplanTable.TopologyPlanRow row = new TopologyplanTable.TopologyPlanRow(this);
1820
                row.copyFrom(topologyPlan);
1821
                row.insert(topologyPlanStore);
1822
            }
1823
            topologyPlanStore.finishEditing();
1824
            
1825
        } catch(Exception ex) {
1826
            LOGGER.warn("Can't update topology plans.", ex);
1827
            status.message("Can't update topology plans");
1828
            FeatureStore.cancelEditingQuietly(topologyPlanStore);
1829
        } finally {
1830
            DisposeUtils.disposeQuietly(request);
1831
            DisposeUtils.disposeQuietly(topologyPlanStore);
1832
        }     
1833
    }
1834
    
1835
    @Override
1836
    public int updateEntitiesFromRepository() {
1837
        return this.updateEntitiesFromRepository(null);
1838
    }
1839

    
1840
    @Override
1841
    public int updateEntitiesFromRepository(SimpleTaskStatus status) {
1842
        LOGGER.debug("===: UPDATE_ENTITIES " + this.getCode() + ", '" + this.getLabel() + "'");
1843
        FeatureStore entitiesStore = null;
1844
        EntitiesTable entitiesTable = new EntitiesTable();
1845
        if (status == null) {
1846
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Update metadata tables");
1847
            status.setAutoremove(true);
1848
            status.add();
1849
        }
1850
        try {
1851
            status.message("Preparing update metadata tables");
1852
            this.reloadRepositoryEntities(status);
1853

    
1854
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1855
            entitiesStore.edit(MODE_FULLEDIT);
1856
            for (VCSGisEntity rentity : this.getRepositoryEntities()) {
1857
                EntityRow entityRow = entitiesTable.getByEntityName(this, rentity.getEntityName());
1858
                if (entityRow != null) {
1859
                    rentity.copyto(entityRow);
1860
                    entityRow.update(entitiesStore);
1861
                }
1862
            }
1863
            entitiesStore.finishEditingQuietly();
1864

    
1865
            this.reloadWorkspaceEntities();
1866
            status.message("Update metadata tables completed");
1867
            status.terminate();
1868
            return ERR_OK;
1869
        } catch (Exception ex) {
1870
            LOGGER.warn("Can't update metadata tables.", ex);
1871
            status.message("Can't update metadata tables");
1872
            status.abort();
1873
            if (entitiesStore != null) {
1874
                entitiesStore.cancelEditingQuietly();
1875
            }
1876
            return ERR_CANT_UPDATE_ENTITIES;
1877
        } finally {
1878
            DisposeUtils.disposeQuietly(entitiesStore);
1879
            entitiesStore = null;
1880
        }
1881
    }
1882

    
1883
    @Override
1884
    public int updatePrepare(String tableName) {
1885
        return updatePrepare(tableName, null);
1886
    }
1887

    
1888
    @Override
1889
    public int updatePrepare(String tableName, SimpleTaskStatus status) {
1890
        LOGGER.debug("===: UPDATE_PREPARE: " + tableName + " WS " + this.getCode() + ", '" + this.getLabel() + "'");
1891
        if (status == null) {
1892
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Update-prepare " + tableName);
1893
            status.setAutoremove(true);
1894
            status.add();
1895
        }
1896

    
1897
        FeatureStore remoteChangesStore = null;
1898
        VCSGisUpdateRequest request = null;
1899
        DisposableIterable<VCSGisRepositoryData> remoteChanges = null;
1900
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1901
        FeatureStore userStore = null;
1902
        FeatureStore localChangesStore = null;
1903
        FeatureStore entitiesStore = null;
1904
        DataTransaction transaction = null;
1905
        try {
1906
            transaction = DALLocator.getDataManager().createTransaction();
1907
            transaction.begin();
1908
            transaction.add(this.getExplorer(), false);
1909

    
1910
            status.message("Preparing update-prepare");
1911
            reloadRepositoryEntities(status);
1912
            request = this.getRepository().createUpdateRequest(tableName);
1913
            transaction.add(request);
1914
            request.setAuthenticationToken(this.authenticationToken);
1915
            request.setUserCode(this.currentUser);
1916
            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
1917
            if (lentity != null) {
1918
                request.setLocalRevisionCode(lentity.getLocalRevisionCode());
1919
            }
1920
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
1921
            transaction.add(entitiesStore);
1922
            status.message("Executing update-prepare request");
1923
            if ( execute(request) != ERR_OK) {
1924
                status.message("Can't update-prepare " + tableName + " (error " + request.getLastErrorCode() + ")");
1925
                status.abort();
1926
                return request.getLastErrorCode();
1927
            }
1928
            entitiesStore.edit(MODE_FULLEDIT);
1929
            status.message("Updating " + tableName + " metadata");
1930
            LOGGER.debug("===: UPDATE_PREPARE: " + tableName + " request code " + request.getCode());
1931
            VCSGisEntity rentity = request.getEntity();
1932
            if (lentity == null) {
1933
                lentity = new EntityRow(this);
1934
                lentity.copyfrom(rentity);
1935
                lentity.setLocalRevisionCode(null);
1936
                lentity.insert(entitiesStore);
1937
            } else {
1938
                lentity.copyfrom(rentity);
1939
                lentity.update(entitiesStore);
1940
            }
1941
//            this.reloadWorkspaceEntities();
1942
            String entityCode = lentity.getCode();
1943
            LOGGER.debug("===: UPDATE_PREPARE: " + tableName + " entity code " + entityCode + ", repo rev. " + lentity.getRepositoryRevisionCode() + ", local rev. " + lentity.getLocalRevisionCode());
1944

    
1945
            status.message("Preparing remote changes container");
1946
            remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
1947
            transaction.add(remoteChangesStore);
1948
            remoteChangesStore.edit(MODE_PASS_THROUGH);
1949

    
1950
            status.message("Deleting previous temporary remote changes");
1951
            LOGGER.debug("===: UPDATE_PREPARE: Delete updates table");
1952
            remoteChangesStore.delete("\"" + COD_ENTITY + "\"='" + entityCode + "'");
1953

    
1954
            remoteChanges = request.getData();
1955
            transaction.add(remoteChanges);
1956
//            long sz = ContainerUtils.size64(remoteChanges);
1957
//            status.setRangeOfValues(0, sz);
1958
            status.setCurValue(0);
1959

    
1960
            LOGGER.debug("===: UPDATE_PREPARE: Inserting updates");
1961
            userStore = this.openFeatureStore(lentity);
1962
            localChangesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
1963
            transaction.add(userStore);
1964
            transaction.add(localChangesStore);
1965
            localChangesStore.edit(MODE_PASS_THROUGH);
1966
            status.message("Downloading list of remote changes");
1967
            for (VCSGisRepositoryData remoteChange : remoteChanges) {
1968
                RemoteChangeRow remoteChangeRow = new RemoteChangeRow(this);
1969
//                LOGGER.debug("===: UPDATE_PREPARE: insert "+remoteChange.getFeatureRelatedCode()+", "+remoteChange.getOperation()+", "+remoteChange.getData());
1970
//                remoteChangeRow.setCode(remoteChange.getFeatureRelatedCode());
1971
                remoteChangeRow.newCode();
1972
                remoteChangeRow.setData(remoteChange.getData());
1973
                remoteChangeRow.setEntityCode(remoteChange.getEntityCode());
1974
                remoteChangeRow.setDataCode(remoteChange.getFeatureRelatedCode());
1975
                remoteChangeRow.setOperation(remoteChange.getOperation());
1976
                remoteChangeRow.setRevisionCode(remoteChange.getRevisionCode());
1977
                remoteChangeRow.setRevisionNumber(remoteChange.getRevisionNumber());
1978
                switch (remoteChange.getOperation()) {
1979
                    case OP_INSERT:
1980
                        remoteChangeRow.setStatus(STATE_LOCAL_NEW);
1981
                        break;
1982
                    case OP_UPDATE:
1983
                    case OP_DELETE:
1984
                        remoteChangeRow.setStatus(STATE_LOCAL_OUTDATED);
1985
                        break;
1986
                    default:
1987
                        remoteChangeRow.setStatus(STATE_LOCAL_UNMODIFIED);
1988
                        break;
1989
                }
1990

    
1991
                if (hasConflictRemoteChangeWithUserTable(lentity, remoteChange, userStore)) {
1992
                    remoteChangeRow.setStatus(STATE_CONFLICT);
1993
                    lentity.setState(STATE_CONFLICT);
1994
                }
1995

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

    
2039
                }
2040
                remoteChangeRow.insert(remoteChangesStore);
2041
                status.incrementCurrentValue();
2042
            }
2043
            LOGGER.debug("===: UPDATE_PREPARE: finish inserting updates");
2044
            lentity.update(entitiesStore);
2045

    
2046
            remoteChangesStore.finishEditing();
2047
            localChangesStore.finishEditing();
2048
            entitiesStore.finishEditing();
2049

    
2050
            updateLocallyModyfiedRemoteChanges();
2051

    
2052
            transaction.commit();
2053

    
2054
            status.message("Update-prepare completed");
2055
            status.terminate();
2056
            return ERR_OK;
2057
        } catch (Exception ex) {
2058
            LOGGER.warn("Can't prepare update.", ex);
2059
            status.message("Can't prepare update");
2060
            status.abort();
2061
            DataTransaction.rollbackQuietly(transaction);
2062
            return ERR_CANT_PREPARE_UPDATE;
2063
        } finally {
2064
            DisposeUtils.disposeQuietly(transaction);
2065
        }
2066

    
2067
    }
2068

    
2069
    private void updateLocallyModyfiedRemoteChanges() {
2070

    
2071
        RemoteChangesTable changes = new RemoteChangesTable();
2072
        changes.updateStateFromLocalChanges(this, STATE_LOCAL_OUTDATED_AND_MODIFIED);
2073

    
2074
    }
2075

    
2076
    private boolean hasConflictRemoteChangeWithUserTable(VCSGisEntity lentity, VCSGisRepositoryData remoteChange, FeatureStore store) throws DataException {
2077
        if (store != null) {
2078
            FeatureType featType = lentity.getFeatureType();
2079
            JsonObject data = remoteChange.getDataAsJson();
2080
            ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
2081
            ExpressionBuilder builder = expManager.createExpressionBuilder();
2082
            builder.set(null);
2083
            for (FeatureAttributeDescriptor attr : featType) {
2084
                if (attr.isIndexed() && !attr.allowIndexDuplicateds()) {
2085
                    Object value = Json.toObject(data, attr.getName());
2086
                    builder.and(
2087
                            builder.eq(
2088
                                    builder.column(attr.getName()),
2089
                                    builder.constant(value)
2090
                            )
2091
                    );
2092

    
2093
                    Feature f = store.findFirst(builder.toString());
2094
                    if (f != null && !StringUtils.equals(
2095
                            f.getString(lentity.getFeatureIdFieldName()),
2096
                            remoteChange.getFeatureRelatedCode())) {
2097
                        return true;
2098
                    }
2099
                }
2100
            }
2101
        }
2102
        return false;
2103
    }
2104

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

    
2170
        FeatureSet feats = store.getFeatureSet(filter.toString());
2171
        return feats.iterable();
2172
    }
2173

    
2174
    @Override
2175
    public int updateClean(String entityCode) {
2176
        return updateClean(entityCode, null);
2177
    }
2178

    
2179
    @Override
2180
    public int updateClean(String entityCode, SimpleTaskStatus status) {
2181
        VCSGisEntity entity = this.getEntity(entityCode);
2182
        if (entity == null) {
2183
            return ERR_ENTITY_NOT_EXISTS;
2184
        }
2185
        if (status == null) {
2186
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2187
                    "Update-clean " + entity.getEntityName()
2188
            );
2189
            status.setAutoremove(true);
2190
            status.add();
2191
        }
2192
        try {
2193
            status.message("Deleting temporary remote changes (" + entity.getEntityName() + ")");
2194
            RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2195
            remoteChangesTable.delete(this, entityCode);
2196
            status.message("Delete temporary remote changes completed");
2197
            status.terminate();
2198
            return ERR_OK;
2199
        } catch (Exception ex) {
2200
            LOGGER.warn("Can't deleting temporary remote changes of " + entity.getEntityName() + ".", ex);
2201
            status.message("Can't deleting temporary remote changes of " + entity.getEntityName() + ".");
2202
            status.abort();
2203
            return ERR_CANT_UPDATE_CLEAN;
2204
        }
2205

    
2206
    }
2207

    
2208
    @Override
2209
    public int update(String tableName) {
2210
        return this.update(tableName, false, false, null);
2211
    }
2212

    
2213
    @Override
2214
    public int update(String tableName, SimpleTaskStatus status) {
2215
        return this.update(tableName, false, false, status);
2216
    }
2217

    
2218
    @Override
2219
    public int merge(String tableName) {
2220
        return this.update(tableName, false, true, null);
2221
    }
2222

    
2223
    @Override
2224
    public int merge(String tableName, SimpleTaskStatus status) {
2225
        return this.update(tableName, false, true, null, status);
2226
    }
2227
    
2228
    @Override
2229
    public int merge(String tableName, MutableLong localChangesCreated, SimpleTaskStatus status) {
2230
        return this.update(tableName, false, true, localChangesCreated, status);
2231
    }
2232

    
2233
    public int update(String tableName, boolean prepare, boolean merge, SimpleTaskStatus status) {
2234
        return update(tableName, prepare, merge, null, status);
2235
    }
2236

    
2237
    public int update(String tableName, boolean prepare, boolean merge, MutableLong localChangesCreated, SimpleTaskStatus status) {
2238
        if(localChangesCreated == null){
2239
            localChangesCreated = new MutableLong(0);
2240
        }
2241
        int errcode = ERR_NO_ERROR;
2242
        if (status == null) {
2243
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2244
                    "Update " + tableName
2245
            );
2246
            status.setAutoremove(true);
2247
            status.add();
2248
        }
2249
        if (prepare) {
2250
            errcode = this.updatePrepare(tableName, status);
2251
            if (errcode != ERR_OK) {
2252
                return errcode;
2253
            }
2254
        }
2255
        LOGGER.debug("===: UPDATE " + this.getCode() + ", '" + this.getLabel() + "', " + tableName);
2256
        RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2257
        WorkspaceChangesTable localChangesTable = new WorkspaceChangesTable();
2258

    
2259
        EditableFeature ef;
2260
        DisposableFeatureSetIterable remoteChanges = null;
2261

    
2262
        FeatureStore workspaceChangesStore = null;
2263
        FeatureStore remoteChangesStore = null;
2264
        FeatureStore userStore = null;
2265
        FeatureStore entitiesStore = null;
2266

    
2267
        DataTransaction transaction = null;
2268
        try {
2269
            transaction = DALLocator.getDataManager().createTransaction();
2270
            transaction.begin();
2271

    
2272
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
2273
            transaction.add(entitiesStore);
2274
            entitiesStore.edit(MODE_PASS_THROUGH);
2275

    
2276
            EntityRow lentity = this.getWorkspaceEntityByName(tableName);
2277
            if (lentity == null) {
2278
                lentity = new EntityRow(this);
2279
                VCSGisEntity rentity = this.getRepositoryEntityByName(tableName);
2280
                lentity.copyfrom(rentity);
2281
                lentity.setLocalRevisionCode(null);
2282
                lentity.update(entitiesStore);
2283
            }
2284
            if (!merge) {
2285
                status.message("Checking the need to merge");
2286
                if (remoteChangesTable.updateNeedMerge(this, lentity.getEntityCode())) {
2287
                    status.message("Can't update without merge.");
2288
                    status.abort();
2289
                    return ERR_UPDATE_NEED_MERGE;
2290
                }
2291
            }
2292
            String dataCodeFieldName = lentity.getFeatureIdFieldName();
2293
            status.message("Searching remote changes (" + lentity.getEntityName() + ")");
2294

    
2295
            userStore = this.openFeatureStore(lentity);
2296
            if (userStore == null) {
2297
                this.create_table(lentity);
2298
                userStore = this.openFeatureStore(lentity);
2299
            }
2300
            transaction.add(userStore);
2301
            userStore.edit(MODE_PASS_THROUGH);
2302

    
2303
            workspaceChangesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
2304
            transaction.add(workspaceChangesStore);
2305
            workspaceChangesStore.edit(MODE_PASS_THROUGH);
2306

    
2307
            remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
2308
            transaction.add(remoteChangesStore);
2309
            remoteChangesStore.edit(MODE_PASS_THROUGH);
2310

    
2311
            remoteChanges = remoteChangesTable.getSelectedsByEntityCodeAsIterator(this, lentity.getCode());
2312
            transaction.add(remoteChanges);
2313
//            long sz = ContainerUtils.size64(remoteChanges);
2314
//            status.setRangeOfValues(0, sz);
2315
            status.setCurValue(0);
2316

    
2317
            if (!remoteChanges.isEmpty()) {
2318
                this.addStoreIgnoreChanges(userStore);
2319
                status.message("Updating table (" + lentity.getEntityName() + ")");
2320
                FeatureType type = userStore.getDefaultFeatureTypeQuietly();
2321

    
2322
                ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
2323
                ExpressionBuilder builder = expManager.createExpressionBuilder();
2324

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

    
2380
                        case OP_DELETE:
2381
                            LOGGER.debug("===: UPDATE: delete");
2382
                            userStore.delete("\"" + dataCodeFieldName + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2383
//                            workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\"='" + remoteChangeRow.getRelatedFeatureCode()+ "'");
2384
                            break;
2385
                    }
2386
                    status.incrementCurrentValue();
2387
                }
2388
            }
2389

    
2390
            if (merge) {
2391
                status.message("Searching local changes to merge (" + lentity.getEntityName() + ")");
2392
                DisposeUtils.disposeQuietly(remoteChanges);
2393
                remoteChanges = remoteChangesTable.getNotSelectedsByEntityCodeAsIterator(this, lentity.getCode());
2394
                transaction.add(remoteChanges);
2395
//                sz = ContainerUtils.size64(remoteChanges);
2396
//                status.setRangeOfValues(0, sz);
2397
                status.setCurValue(0);
2398

    
2399
                if (!remoteChanges.isEmpty()) {
2400
                    //We edit the changesStore because we will need local changes 
2401
//                    workspaceChangesStore.edit(MODE_PASS_THROUGH);
2402

    
2403
                    //We edit the destination store because we may need to update some features (in case OP_DELETE)
2404
//                    userStore.edit(MODE_PASS_THROUGH);
2405
                    this.addStoreIgnoreChanges(userStore);
2406

    
2407
                    status.message("Adding to local changes (" + lentity.getEntityName() + ")");
2408
                    for (Feature feature : remoteChanges) {
2409
                        RemoteChangeRow remoteChangeRow = new RemoteChangeRow(this, feature);
2410
                        Feature f = userStore.findFirst("\"" + lentity.getFeatureIdFieldName() + "\" = '" + remoteChangeRow.getRelatedFeatureCode() + "'");
2411
                        switch (remoteChangeRow.getOperation()) {
2412
                            case OP_INSERT:
2413
                                LOGGER.debug("===: UPDATE: insert");
2414
                                if (f == null) {
2415
                                    this.addDeleteChange(lentity, workspaceChangesStore, remoteChangeRow.getRelatedFeatureCode(), null, null);
2416
                                } else {
2417
                                    this.addChange(lentity, OP_UPDATE, workspaceChangesStore, f, null);
2418
                                }
2419
                                localChangesCreated.increment();
2420
                                break;
2421

    
2422
                            case OP_UPDATE:
2423
                                LOGGER.debug("===: UPDATE: update");
2424
                                if (f == null) {
2425
                                    this.addDeleteChange(lentity, workspaceChangesStore, remoteChangeRow.getRelatedFeatureCode(), null, null);
2426
                                } else {
2427
                                    this.addChange(lentity, OP_UPDATE, workspaceChangesStore, f, null);
2428
                                }
2429
                                localChangesCreated.increment();
2430
                                break;
2431
                            case OP_DELETE:
2432
                                LOGGER.debug("===: UPDATE: delete");
2433
                                if (f != null) {
2434
                                    userStore.delete("\"" + dataCodeFieldName + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2435

    
2436
                                    ef = userStore.createNewFeature(f);
2437
                                    ef.setString(lentity.getFeatureIdFieldName(), this.createUniqueCode());
2438
                                    userStore.insert(ef);
2439

    
2440
                                    workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2441
                                    this.addChange(lentity, OP_INSERT, workspaceChangesStore, ef, null);
2442
                                    localChangesCreated.increment();
2443
                                }
2444
                                break;
2445
                        }
2446
                        status.incrementCurrentValue();
2447
                    }
2448
                }
2449
            }
2450
            localChangesTable.removeLocalChangesRelatedToSelectedRemoteChanges(this, lentity);
2451
            remoteChangesTable.delete(remoteChangesStore, lentity.getEntityCode());
2452

    
2453
            status.message("Updating metadata tables");
2454
            lentity.setLocalRevisionCode(lentity.getRepositoryRevisionCode());
2455
            lentity.update(entitiesStore);
2456
            forceReloadWorkspaceEntities();
2457

    
2458
            transaction.commit();
2459

    
2460
            status.message("Update completed");
2461
            status.terminate();
2462
            return ERR_OK;
2463
        } catch (Exception ex) {
2464
            LOGGER.warn("Can't update.", ex);
2465
            status.message("Can't update");
2466
            status.abort();
2467
            return ERR_CANT_UPDATE;
2468
        } finally {
2469
            this.removeStoreIgnoreChanges(userStore);
2470
            DisposeUtils.disposeQuietly(transaction);
2471
        }
2472
    }
2473

    
2474
    @Override
2475
    public JDBCServerExplorer getExplorer() {
2476
        return this.wsexplorer;
2477
    }
2478

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

    
2612
            Map<String, VCSGisEntity> tmp = new HashMap<>();
2613
            entities.forEach(entity -> {
2614
                tmp.put(entity.getEntityCode(), entity);
2615
            });
2616
            this.repositoryEntitiesByCode = tmp;
2617
            
2618
            Map<String, EntityRow> theEntitiesByName = new HashMap<>();
2619
            Map<String, EntityRow> theEntitiesByCode = new HashMap<>();
2620

    
2621
            store = openFeatureStore(EntitiesTable.TABLE_NAME);
2622
            store.edit();
2623
            fset = store.getFeatureSet();
2624
            for (Feature feature : fset.iterable()) {
2625
                EntityRow entity = new EntityRow(this, feature);
2626
                VCSGisEntity repositoryEntity = this.repositoryEntitiesByCode.get(entity.getEntityCode());
2627
                if(repositoryEntity != null && !StringUtils.equalsIgnoreCase(entity.getRepositoryRevisionCode(),repositoryEntity.getRepositoryRevisionCode())){
2628
                    entity.setRepositoryRevisionCode(repositoryEntity.getRepositoryRevisionCode());
2629
                    entity.setTopologyPlanCode(repositoryEntity.getTopologyPlanCode());
2630
                    entity.update(store, fset);
2631
                }
2632
                theEntitiesByName.put(entity.getEntityName(), entity);
2633
                theEntitiesByCode.put(entity.getCode(), entity);
2634
            }
2635
            store.finishEditing();
2636
            this.workspaceEntitiesByName = theEntitiesByName;
2637
            this.workspaceEntitiesByCode = theEntitiesByCode;
2638

    
2639
            status.message("Repository tables metadata update completed");
2640
            if (isMyStatus) {
2641
                status.terminate();
2642
            }
2643
            this.repositoryEntitiesChangeListeners.fireEvent();
2644
            this.workspaceEntitiesChangeListeners.fireEvent();
2645
        } catch (VCSGisRuntimeException ex) {
2646
            FeatureStore.cancelEditingQuietly(store);
2647
            status.message("Can't get repository tables metadata");
2648
            if (isMyStatus) {
2649
                status.abort();
2650
            }
2651
            throw ex;
2652
        } catch (Exception ex) {
2653
            FeatureStore.cancelEditingQuietly(store);
2654
            status.message("Can't get repository tables metadata");
2655
            if (isMyStatus) {
2656
                status.abort();
2657
            }
2658
            throw new VCSGisRuntimeException(ERR_CANT_RETRIEVE_ENTITIES, VCSGisUtils.getErrorMessage(ERR_CANT_RETRIEVE_ENTITIES), ex);
2659
        } finally {
2660
            DisposeUtils.disposeQuietly(fset);
2661
            DisposeUtils.disposeQuietly(store);
2662
        }
2663
    }
2664

    
2665
    private boolean hasRepositoryEntities() {
2666
        return this.repositoryEntitiesByCode != null;
2667
    }
2668
    
2669
    @Override
2670
    public List<VCSGisEntity> getRepositoryEntities() {
2671
        if (this.repositoryEntitiesByCode == null) {
2672
            reloadRepositoryEntities(null);
2673
        }
2674
        List<VCSGisEntity> entities = new ArrayList<>(this.repositoryEntitiesByCode.values());
2675
        return entities;
2676
    }
2677

    
2678
    @Override
2679
    public boolean updateNeedMerge(String entityName) {
2680
        RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2681

    
2682
        VCSGisEntity entity = this.getWorkspaceEntity(entityName);
2683
        if (entity == null) {
2684
            entity = this.getRepositoryEntity(entityName);
2685
        }
2686

    
2687
        return remoteChangesTable.updateNeedMerge(this, entity.getEntityCode());
2688
    }
2689

    
2690
    @Override
2691
    public void addToConnectionPool() {
2692
        JDBCServerExplorerParameters params = this.getExplorerParameters();
2693
        DataManager dataManager = DALLocator.getDataManager();
2694
        dataManager.getDataServerExplorerPool().add(this.getLabel(), params);
2695
    }
2696

    
2697
    @Override
2698
    public boolean isInMyDatabase(FeatureStore store) {
2699
        if (!(store.getParameters() instanceof JDBCStoreParameters)) {
2700
            return false;
2701
        }
2702
        JDBCStoreParameters storeParams = (JDBCStoreParameters) store.getParameters();
2703
        JDBCServerExplorerParameters explorerParams = this.getExplorerParameters();
2704
        if (!StringUtils.equalsIgnoreCase(storeParams.getProviderName(), explorerParams.getProviderName())) {
2705
            return false;
2706
        }
2707
        return StringUtils.equalsIgnoreCase(storeParams.getUrl(), explorerParams.getUrl());
2708
    }
2709

    
2710
    @Override
2711
    public int history(String entityName, String group, Timestamp minDate, Timestamp maxDate, int maxNumberOfRevisions, SimpleTaskStatus status) {
2712
        int errcode = ERR_OK;
2713
        if (status == null) {
2714
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2715
                    "History" + entityName
2716
            );
2717
            status.setAutoremove(true);
2718
            status.add();
2719
        }
2720
        if (maxNumberOfRevisions < 0) {
2721
            maxNumberOfRevisions = 1000;
2722
        }
2723
        if (minDate != null && maxDate != null && minDate.compareTo(maxDate) > 0) {
2724
            Timestamp x = minDate;
2725
            minDate = maxDate;
2726
            maxDate = x;
2727
        }
2728
        DataTransaction transaction = DALLocator.getDataManager().createTransaction();
2729
        try {
2730
            LOGGER.debug("===: HISTORY " + this.getCode() + ", '" + this.getLabel() + "', " + entityName);
2731
            reloadWorkspaceEntities();
2732

    
2733
            VCSGisEntity lentity = this.getEntity(entityName);
2734
            if (lentity == null) {
2735
                status.message("Can't find table '" + entityName + "'");
2736
                status.abort();
2737
                return ERR_ENTITY_NOT_EXISTS;
2738
            }
2739

    
2740
            status.message("Executing history request");
2741
            VCSGisHistoryRequest request = this.getRepository().createHistoryRequest(entityName);
2742
            transaction.add(request);
2743

    
2744
            request.setAuthenticationToken(this.authenticationToken);
2745
            request.setUserCode(this.currentUser);
2746
            request.setDateRange(minDate, maxDate);
2747
            request.setMaxNumberOfRevisions(maxNumberOfRevisions);
2748
            request.setRevisionNumberRange(-1, -1);
2749

    
2750
            if ( execute(request) != ERR_OK) {
2751
                status.message("Can't retriev history of " + entityName + " (error " + request.getLastErrorCode() + ")");
2752
                status.abort();
2753
                return request.getLastErrorCode();
2754
            }
2755
            LocalRevisionsTable localRevisionsTable = new LocalRevisionsTable();
2756
            FeatureStore localRevisionsStore = this.openFeatureStore(LocalRevisionsTable.TABLE_NAME);
2757
            transaction.add(localRevisionsStore);
2758
            localRevisionsStore.edit(MODE_PASS_THROUGH);
2759

    
2760
            status.message("Deleting previous local revision information");
2761
            localRevisionsTable.deleteByEntityCodeAndGroup(
2762
                    this,
2763
                    localRevisionsStore,
2764
                    lentity.getEntityCode(),
2765
                    group
2766
            );
2767

    
2768
            DisposableIterable<VCSGisRevision> revisions = request.getRevisions();
2769
            status.message("Adding to local revisions");
2770
//            long sz = ContainerUtils.size64(revisions);
2771
//            status.setRangeOfValues(0, sz);
2772
            status.setCurValue(0);
2773

    
2774
            long minRevision = -1;
2775
            minDate = now();
2776
            errcode = ERR_CANT_INSERT_FEATURES;
2777
            for (VCSGisRevision revision : revisions) {
2778
                LocalRevisionRow row = new LocalRevisionRow(this);
2779
                row.copyFrom(revision);
2780
                row.setGroup(group);
2781
                row.insert(localRevisionsStore);
2782
                if (minRevision < 0 || minRevision > row.getNumber()) {
2783
                    minRevision = row.getNumber();
2784
                }
2785
                if (minDate.compareTo(row.getRevisionDate()) > 0) {
2786
                    minDate = row.getRevisionDate();
2787
                }
2788
                status.incrementCurrentValue();
2789
            }
2790
            localRevisionsStore.finishEditing();
2791

    
2792
            VarsTable varsTable = new VarsTable();
2793
            varsTable.set(
2794
                    this,
2795
                    "history_" + entityName + "_" + group + "_MinDate",
2796
                    minDate.toString()
2797
            );
2798
            varsTable.set(
2799
                    this,
2800
                    "history_" + entityName + "_" + group + "_MinRevision",
2801
                    String.valueOf(minRevision)
2802
            );
2803

    
2804
            transaction.commit();
2805
            status.message("History completed");
2806
            status.terminate();
2807
            return ERR_OK;
2808
        } catch (Exception ex) {
2809
            LOGGER.warn("Can't retrieve history.", ex);
2810
            transaction.rollbackQuietly();
2811
            status.message("Can't retrieve history");
2812
            status.abort();
2813
            return errcode;
2814
        } finally {
2815
            transaction.dispose();
2816
        }
2817
    }
2818

    
2819
    @Override
2820
    public int history(String entityName, String group, int maxNumberOfRevisions, SimpleTaskStatus status) {
2821
        int errcode = ERR_OK;
2822
        if (status == null) {
2823
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
2824
                    "History" + entityName
2825
            );
2826
            status.setAutoremove(true);
2827
            status.add();
2828
        }
2829
        if (maxNumberOfRevisions < 0) {
2830
            maxNumberOfRevisions = 1000;
2831
        }
2832
        DataTransaction transaction = DALLocator.getDataManager().createTransaction();
2833
        try {
2834
            LOGGER.debug("===: HISTORY " + this.getCode() + ", '" + this.getLabel() + "', " + entityName);
2835
            reloadWorkspaceEntities();
2836

    
2837
            EntityRow lentity = this.getWorkspaceEntityByName(entityName);
2838
            if (lentity == null) {
2839
                status.message("Can't find table '" + entityName + "'");
2840
                status.abort();
2841
                return ERR_ENTITY_NOT_EXISTS;
2842
            }
2843
            VarsTable varsTable = new VarsTable();
2844

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

    
2847
            status.message("Executing history request");
2848
            VCSGisHistoryRequest request = this.getRepository().createHistoryRequest(entityName);
2849
            transaction.add(request);
2850

    
2851
            request.setAuthenticationToken(this.authenticationToken);
2852
            request.setUserCode(this.currentUser);
2853
            request.setDateRange(null, null);
2854
            request.setMaxNumberOfRevisions(maxNumberOfRevisions);
2855
            request.setRevisionNumberRange(-1, minRevision);
2856

    
2857
            if ( execute(request) != ERR_OK) {
2858
                status.message("Can't retriev history of " + entityName + " (error " + request.getLastErrorCode() + ")");
2859
                status.abort();
2860
                return request.getLastErrorCode();
2861
            }
2862
            FeatureStore localRevisionsStore = this.openFeatureStore(LocalRevisionsTable.TABLE_NAME);
2863
            transaction.add(localRevisionsStore);
2864
            localRevisionsStore.edit(MODE_PASS_THROUGH);
2865

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

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

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

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

    
2918
    @Override
2919
    public GetItemWithSize64<VCSGisRevision> getRevisions(String entityName, String group) {
2920
        LocalRevisionsTable localRevisionsTable = new LocalRevisionsTable();
2921
        reloadWorkspaceEntities();
2922

    
2923
        VCSGisEntity lentity = this.getEntity(entityName);
2924
        if (lentity == null) {
2925
            throw new IllegalArgumentException("EntityName '" + entityName + "' not found.");
2926
        }
2927
        final VCSGisWorkspaceImpl workspace = this;
2928
        final GetItemWithSizeAndIterator64<Feature> revisionsf = localRevisionsTable.getRevisions(this, lentity.getEntityCode(), group);
2929
        GetItemWithSize64<VCSGisRevision> revisions = new GetItemWithSize64<VCSGisRevision>() {
2930
            @Override
2931
            public long size64() {
2932
                return revisionsf.size64();
2933
            }
2934

    
2935
            @Override
2936
            public VCSGisRevision get64(long position) {
2937
                Feature f = revisionsf.get64(position);
2938
                LocalRevisionRow revision = new LocalRevisionRow(workspace, f);
2939
                return revision;
2940
            }
2941
        };
2942
        return revisions;
2943
    }
2944

    
2945
    @Override
2946
    public String getUserName(String userCode) {
2947
        return null;
2948
    }
2949

    
2950
    @Override
2951
    public VCSGisUser getUser(String userCode) {
2952
        return null;
2953
    }
2954

    
2955
    @Override
2956
    public Feature getRelatedFeature(VCSGisEntity entity, String featureCode) {
2957
        try {
2958
            FeatureStore store = this.getFeatureStore(entity.getEntityName());
2959
            Feature f = store.findFirst("\"" + entity.getFeatureIdFieldName() + "\"='" + featureCode + "'");
2960
            return f;
2961
        } catch (Exception ex) {
2962
            throw new RuntimeException("Can't retrieve feature '" + entity.getEntityName() + "/" + code + "'.", ex);
2963
        }
2964

    
2965
    }
2966

    
2967
    @Override
2968
    public Feature getRelatedFeature(VCSGisRepositoryChange change) {
2969
        EntityRow entity = this.getWorkspaceEntity(change.getEntityCode());
2970
        return getRelatedFeature(entity, change.getRelatedFeatureCode());
2971
    }
2972
    
2973
    @Override
2974
    public int removeEntity(String nameOrCode) {
2975
        int err = ERR_NO_ERROR;
2976
        EntityRow entity = this.getWorkspaceEntity(nameOrCode);
2977
        if(entity == null){
2978
            err = ERR_ENTITY_NOT_EXISTS;
2979
            return err;
2980
        }
2981

    
2982
        DataTransaction transaction = DALLocator.getDataManager().createTransaction();
2983
        try {
2984
            LOGGER.debug("===: REMOVE ENTITY " + entity.getEntityName());
2985

    
2986

    
2987
            //Eliminamos todos los cambios de esta entidad
2988
            err = ERR_CANT_REMOVE_CHANGES;
2989
            FeatureStore changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
2990
            transaction.add(changesStore);
2991
            changesStore.edit(MODE_FULLEDIT);
2992
            changesStore.delete("\""+WorkspaceChangesTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
2993
            changesStore.finishEditing();
2994

    
2995
            FeatureStore remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME);
2996
            transaction.add(remoteChangesStore);
2997
            remoteChangesStore.edit(MODE_FULLEDIT);
2998
            remoteChangesStore.delete("\""+RemoteChangesTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
2999
            remoteChangesStore.finishEditing();
3000

    
3001
            //Eliminamos las revisiones locales
3002
            FeatureStore revisionsStore = openFeatureStore(LocalRevisionsTable.TABLE_NAME);       
3003
            transaction.add(revisionsStore);
3004
            revisionsStore.edit(MODE_FULLEDIT);
3005
            revisionsStore.delete("\""+LocalRevisionsTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3006
            revisionsStore.finishEditing();
3007
            err = ERR_CANT_REMOVE_ENTITY;
3008

    
3009

    
3010
            //Eliminamos la entidad
3011
            FeatureStore entitiesStore = openFeatureStore(EntitiesTable.TABLE_NAME);       
3012
            transaction.add(entitiesStore);
3013
            entitiesStore.edit(MODE_FULLEDIT);
3014
            entitiesStore.delete("\""+EntitiesTable.COD_ENTITY+"\"='"+entity.getEntityCode()+"'");
3015
            entitiesStore.finishEditing();
3016
            err = ERR_CANT_REMOVE_ENTITY;
3017

    
3018

    
3019
            //Eliminamos el DALFILE
3020
            FeatureStore store = this.openFeatureStore(entity);
3021
            if(store != null){
3022
                transaction.add(store);
3023
                ResourcesStorage resourcesStorage = store.getResourcesStorage();
3024
                if (resourcesStorage != null) {
3025
                    Resource resource = resourcesStorage.getResource("dal");
3026
                    if (resource != null) {
3027
                        resourcesStorage.remove(resource.getName());
3028
                    }
3029
                }
3030
            
3031
                //Eliminamos el store
3032
                transaction.add(this.wsexplorer, false);
3033
                this.wsexplorer.remove(store.getParameters());
3034
            }
3035
            
3036
            forceReloadWorkspaceEntities();
3037
            transaction.commit();
3038
            return ERR_OK;
3039
        } catch (Exception ex) {
3040
            LOGGER.warn("Can't remove entity.", ex);
3041
            transaction.rollbackQuietly();
3042
            return err;
3043
        } finally {
3044
            transaction.dispose();
3045
        }
3046
        
3047
    }
3048

    
3049
    public int authenticate(String userId, String password, SimpleTaskStatus status) {
3050
        int errcode = ERR_OK;
3051
        if (status == null) {
3052
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(
3053
                    "Authenticate-" + userId
3054
            );
3055
            status.setAutoremove(true);
3056
            status.add();
3057
        }
3058
        try {
3059
            VCSGisAuthenticateRequest request = this.getRepository().createAuthenticateRequest(userId, password);
3060
            if ( execute(request) != ERR_OK) {
3061
                status.message(request.getLastErrorMessage());
3062
                status.abort();
3063
                return request.getLastErrorCode();
3064
            }
3065
            VarsTable varsTable = new VarsTable();
3066
            varsTable.set(this,"USER",request.getUserCode());
3067
            varsTable.set(this,"AUTHENTICATIONTOKEN",request.getAuthenticationToken());
3068
            this.currentUser = request.getUserCode();
3069
            this.authenticationToken = request.getAuthenticationToken();
3070
            this.getRepository().setAuthenticationToken(request.getAuthenticationToken());
3071
            this.getRepository().setUserCode(request.getUserCode());
3072
            
3073
            status.message("Authentication completed");
3074
            status.terminate();
3075
            return ERR_OK;
3076
        } catch (Exception ex) {
3077
            LOGGER.warn("Can't authenticate user.", ex);
3078
            status.message("Can't authenticate user");
3079
            status.abort();
3080
            return errcode;
3081
        }
3082
    }
3083

    
3084
    @Override
3085
    public void setUserIdentificationRequester(VCSGisUserIdentificationRequester userIdentificationRequester) {
3086
        this.userIdentificationRequester = userIdentificationRequester;
3087
    }
3088

    
3089
    @Override
3090
    public VCSGisUserIdentificationRequester getUserIdentificationRequester() {
3091
        return this.userIdentificationRequester;
3092
    }
3093

    
3094
    private int execute(VCSGisRequest request) {
3095
        while(true) {
3096
            switch(request.execute()) {
3097
                case ERR_CANT_AUTHENTICATE_USER:
3098
                case ERR_INVALID_AUTHENTICATION_TOKEN:
3099
                case ERR_USER_NOT_AUTHORIZED:
3100
                case ERR_AUTHENTICATION_EXPIRED:
3101
                case ERR_INVALID_USERCODE:
3102
                    if( this.userIdentificationRequester!= null ) {
3103
                        if( this.userIdentificationRequester.requestIdentification() ) {
3104
                            int r = this.authenticate(this.userIdentificationRequester.getUserId(), this.userIdentificationRequester.getPassword(), null);
3105
                            if(r == ERR_OK){
3106
                                request.setAuthenticationToken(this.authenticationToken);
3107
                                request.setUserCode(this.currentUser);
3108
                            }
3109
                            continue;
3110
                        }
3111
                    }
3112
                    // don't break
3113
                default:
3114
                    return request.getLastErrorCode();            
3115
            }
3116
        }
3117
    }
3118

    
3119

    
3120
    // TODO: eliminar la constante y contains para usar las de tools.
3121
    public static final Comparator<String> EQUALS_IGNORECASE_COMPARATOR = (Comparator<String>) (String o1, String o2) -> StringUtils.compareIgnoreCase(o1, o2);
3122
    public static boolean contains(Collection collection, Object value, Comparator comparator) {
3123
        for (Object item : collection) {
3124
            if( comparator.compare(item, value)==0 ) {
3125
                return true;
3126
            }
3127
        }
3128
        return false;
3129
    }
3130

    
3131
    @Override
3132
    public Collection<String> getEntityCategories() {
3133
        List<String> categories = new ArrayList<>();
3134
        if( this.hasRepositoryEntities() ) {
3135
            for (VCSGisEntity entity : this.getRepositoryEntities()) {
3136
                String category = entity.getCategory();
3137
                if( StringUtils.isNotBlank(category) ) {
3138
                    if( !contains(categories, category, EQUALS_IGNORECASE_COMPARATOR) ) {
3139
                        categories.add(category);
3140
                    }
3141
                }
3142
            }
3143
        }
3144
        for (VCSGisEntity entity : this.getWorkspaceEntities()) {
3145
            String category = entity.getCategory();
3146
            if( StringUtils.isNotBlank(category) ) {
3147
                if( !contains(categories, category, EQUALS_IGNORECASE_COMPARATOR) ) {
3148
                    categories.add(category);
3149
                }
3150
            }
3151
        }
3152
        Collections.sort(categories);
3153
        return Collections.unmodifiableCollection(categories);
3154
    }
3155
    
3156
    @Override
3157
    public String getTopologyPlan(String topologyPlanCode) {
3158
        if( StringUtils.isBlank(topologyPlanCode) ) {
3159
            return null;
3160
        }
3161
        TopologyplanTable topologyplanTable = new TopologyplanTable();
3162
        return topologyplanTable.getByCode(this, topologyPlanCode);
3163
    }
3164
    
3165
    @Override
3166
    public int importHistory(FeatureStore sourceStore,
3167
            String name,
3168
            String label,
3169
            String category,
3170
            String attrNameForLabel,
3171
            String fieldCodeName,
3172
            String fieldDateName,
3173
            String fieldOrderName) {
3174
        
3175
            I18nManager i18n = ToolsLocator.getI18nManager();
3176
            SimpleTaskStatus status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(i18n.getTranslation("_Import_history"));
3177
            status.setAutoremove(true);
3178
            status.add();
3179
            
3180
            FeatureStore target = null;
3181
            FeatureSet features = null;
3182
            
3183
        try{
3184
            VCSGisRepository repo = this.getRepository();
3185
            if (repo instanceof VCSGisRepositoryLocaldb){
3186
                ((VCSGisRepositoryLocaldb) repo).setAllowAssignTheRevisionDate(true);
3187
            }
3188
            
3189
            int result = this.addEntity(
3190
                    sourceStore.getDefaultFeatureTypeQuietly(),
3191
                    name, 
3192
                    null,
3193
                    attrNameForLabel, 
3194
                    category, 
3195
                    label,
3196
                    null
3197
            );
3198
            target = this.openFeatureStore(name);
3199
            FeatureQuery query = sourceStore.createFeatureQuery();
3200
            ExpressionBuilder expBuilder = ExpressionUtils.createExpressionBuilder();
3201
            query.getOrder().add(fieldDateName, true);
3202
            query.getOrder().add(fieldOrderName, true);
3203
            features = sourceStore.getFeatureSet(query);
3204
            target.edit(MODE_PASS_THROUGH);
3205
            Timestamp lastRevisionDate=null;
3206
            status.setRangeOfValues(0, features.size64());
3207
            status.setCurValue(0);
3208
            for (Feature sourceFeature : features) {
3209
                String filter = expBuilder.eq(expBuilder.column(fieldCodeName),
3210
                        expBuilder.constant(sourceFeature.get(fieldCodeName))
3211
                ).toString();
3212
                Feature targetFeature = target.findFirst(filter);
3213
                if (targetFeature == null) {
3214
                    if (lastRevisionDate==null){
3215
                        lastRevisionDate=sourceFeature.getTimestamp(fieldDateName);
3216
                    }
3217
                    if (Objects.equals(lastRevisionDate, sourceFeature.getTimestamp(fieldDateName))){
3218
                        EditableFeature editableTargetFeature = target.createNewFeature(sourceFeature);
3219
                        target.insert(editableTargetFeature);
3220
                    }else{
3221
                        result = this.commit(lastRevisionDate, lastRevisionDate, null, null);
3222
                        if (result!=ERR_OK){
3223
                            return result;
3224
                        }
3225
                        EditableFeature editableTargetFeature = target.createNewFeature(sourceFeature);
3226

    
3227
                        target.insert(editableTargetFeature);
3228
                        lastRevisionDate=sourceFeature.getTimestamp(fieldDateName);                       
3229
                    }
3230
                
3231
                }else{
3232
                    EditableFeature ef = targetFeature.getEditable();
3233
                    ef.copyFrom(sourceFeature);
3234
                    ef.setUpdatable(true);
3235
                    target.update(ef);
3236
                }
3237
                status.incrementCurrentValue();
3238
            }
3239
            result = this.commit(lastRevisionDate, lastRevisionDate, null, null);
3240
            if (result!=ERR_OK){
3241
                return result;
3242
            }
3243
            target.finishEditing();
3244
            status.terminate();
3245
            return ERR_OK;
3246
        }catch(Exception ex){
3247
            status.abort();
3248
            return -1;
3249
        }finally{
3250
            DisposeUtils.disposeQuietly(features);
3251
            DisposeUtils.disposeQuietly(target);
3252
        }
3253
    }
3254
    public int revert(String nameOrCode) {
3255
        return revert(nameOrCode, null);
3256
    }
3257
    
3258
    @Override
3259
    public int revert(String nameOrCode, SimpleTaskStatus status) {
3260
        if (status == null) {
3261
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Commit");
3262
            status.setAutoremove(true);
3263
            status.add();
3264
        }
3265

    
3266
//        FeatureStore entitiesStore = null;
3267

    
3268
        DataTransaction transaction = null;
3269
        try {
3270
            LOGGER.debug("===: REVERT " + this.getCode() + ", " + this.getLabel() + ", " + nameOrCode);
3271
            transaction = DALLocator.getDataManager().createTransaction();
3272
            transaction.begin();
3273
            
3274
            status.message("Reverting");
3275
            
3276
            EntityRow entity = this.getWorkspaceEntity(nameOrCode);
3277
            WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
3278
            FeatureStore userStore = null;
3279
            FeatureStore changesStore = null;
3280
//            String dataCodeFieldName = entity.getFeatureIdFieldName();
3281

    
3282
            DisposableFeatureSetIterable changes = changesTable.getSelectedsByEntityCodeAsIterator(this, entity.getEntityCode());
3283
            transaction.add(changes);
3284

    
3285

    
3286
            if (!changes.isEmpty()) {
3287
                userStore = this.openFeatureStore(entity);
3288
                transaction.add(userStore, true);
3289
                userStore.edit(MODE_PASS_THROUGH);
3290
                changesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME);
3291
                transaction.add(changesStore, true);
3292
                changesStore.edit(MODE_PASS_THROUGH);
3293

    
3294
                status.setCurValue(0);
3295
                status.setRangeOfValues(0, changes.size64());
3296
                for (Feature feature : changes) {
3297
                    WorkspaceChangeRow change = new WorkspaceChangeRow(this, feature);
3298
                    change.revert(userStore, changesStore);
3299
//                    String data = change.getData();
3300
//                    JsonObject dataAsJson = change.getDataAsJson();
3301
//                    int operation = change.getOperation();
3302
//                    switch (change.getOperation()) {
3303
//                        case OP_ADD_ENTITY:
3304
//                            //TODO: remove entity ???
3305
////                            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
3306
////                            transaction.add(entitiesStore);
3307
////                            entitiesStore.edit(MODE_PASS_THROUGH);
3308
//                            break;
3309
//                        case OP_INSERT:
3310
//                            // Remove related feature
3311
//                            LOGGER.debug("===: REVERT: insert");
3312
//                            userStore.delete("\"" + dataCodeFieldName + "\"='" + change.getRelatedFeatureCode() + "'");
3313
//                            break;
3314
//                        case OP_UPDATE:
3315
//                            // Update related feature from old feature
3316
//                            Feature relatedFeature = change.getRelatedFeature();
3317
//                            EditableFeature ef = relatedFeature.getEditable();
3318
//                            ef.copyFrom(change.getDataAsJson());
3319
//                            userStore.update(ef);
3320
//                            break;
3321
//                        case OP_DELETE:
3322
//                            //Create new feature from old feature
3323
//                            JsonObject dataJson = change.getDataAsJson();
3324
//                            ef = userStore.createNewFeature(dataJson);
3325
//                            userStore.insert(ef);
3326
//                            break;
3327
//                    }
3328
                    status.incrementCurrentValue();
3329
                }
3330
                userStore.finishEditing();
3331
                changesStore.finishEditing();
3332
            }
3333
            
3334

    
3335
//            LOGGER.debug("===: REVERT: clean local changes");
3336
//            status.message("Removing local list of changes");
3337
//            changesTable.deleteSelectedsByEntity(this, entity.getEntityCode());
3338

    
3339
            status.message("Revert completed");
3340
            status.terminate();
3341
            return ERR_NO_ERROR;
3342
        } catch (Exception ex) {
3343
            LOGGER.warn("Can't revert changes.", ex);
3344
            status.message("Can't revert changes");
3345
            status.abort();
3346
            return ERR_CANT_REVERT;
3347
        } finally {
3348
            DisposeUtils.disposeQuietly(transaction);
3349
        }
3350
    }
3351
    
3352
    @Override
3353
    public int export(String entityName, String tableName, String revisionCode, Timestamp efectiveDate, SimpleTaskStatus status) {
3354
        FeatureStore target = null;
3355
        FeatureStore entitiesStore = null;
3356
        int errcode = ERR_OK;
3357
        VCSGisCheckoutRequest request = null;
3358
        if (status == null) {
3359
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("_Export");
3360
            status.setAutoremove(true);
3361
            status.add();
3362
        }
3363
        try {
3364
            LOGGER.debug("===: EXPORT " + this.getCode() + ", '" + this.getLabel() + "', " + tableName);
3365
            status.message("Preparing export");
3366
            VCSGisEntity lentity = this.getEntity(entityName);
3367
            if (lentity == null) {
3368
                status.message("Table " + tableName + " not exists");
3369
                status.abort();
3370
                return ERR_ENTITY_NOT_EXISTS;
3371
            }
3372
            reloadRepositoryEntities(status);
3373
            request = this.getRepository().createCheckoutRequest(entityName);
3374
            request.setAuthenticationToken(this.authenticationToken);
3375
            request.setUserCode(this.currentUser);
3376
            request.setEfectiveDate(efectiveDate);
3377
            request.setRevisionCode(revisionCode);
3378

    
3379
            status.message("Executing export request for " + tableName);
3380
            if ( execute(request) != ERR_OK) {
3381
                status.message("Can't export " + tableName + " (error " + request.getLastErrorCode() + ")");
3382
                status.abort();
3383
                return request.getLastErrorCode();
3384
            }
3385
            status.message("Updating " + tableName + " metadata");
3386
//            VCSGisEntity rentity = request.getEntity();
3387
//            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME);
3388
//            entitiesStore.edit(FeatureStore.MODE_FULLEDIT);
3389
//            VCSGisEntity rentity = request.getEntity();
3390
//            lentity = new EntityRow(this);
3391
//            rentity.copyto(lentity);
3392
//            lentity.insert(entitiesStore);
3393
//            LOGGER.debug("===: CHECKOUT " + this.getCode() + ", '" + this.getLabel() + "', " + tableName + ", rev." + rentity.getRepositoryRevisionCode());
3394

    
3395
//            this.forceReloadWorkspaceEntities();
3396
            status.message("Creating table " + tableName);
3397
            this.create_table(lentity, tableName);
3398

    
3399
            status.message("Adding features in " + tableName);
3400
            errcode = ERR_CANT_OPEN_STORE;
3401
            target = this.openFeatureStore(tableName);
3402
            this.addStoreIgnoreChanges(target);
3403
            DisposableIterable<VCSGisRepositoryData> data = request.getData();
3404
//            long sz = ContainerUtils.size64(data); // Con tablas tochas esto deja frita la app.
3405
//            status.setRangeOfValues(0, sz);
3406
            status.setCurValue(0);
3407
            errcode = ERR_CANT_INSERT_FEATURES;
3408
            target.edit(FeatureStore.MODE_APPEND);
3409
            for (VCSGisRepositoryData d : data) {
3410
                EditableFeature f = target.createNewFeature(d.getDataAsJson());
3411
                target.insert(f);
3412
                status.incrementCurrentValue();
3413
            }
3414
            target.finishEditing();
3415

    
3416
            status.message("Updating " + tableName + " metadata");
3417
//            if(StringUtils.isBlank(revisionCode)){
3418
//                lentity.setLocalRevisionCode(rentity.getRepositoryRevisionCode());
3419
//            } else {
3420
//                lentity.setLocalRevisionCode(revisionCode);
3421
//            }
3422
//            lentity.update(entitiesStore);
3423
//            entitiesStore.finishEditing();
3424
//            this.forceReloadWorkspaceEntities();
3425
            request.dispose();
3426

    
3427
            status.message("Export completed");
3428
            status.terminate();
3429
            return ERR_NO_ERROR;
3430
        } catch (Exception ex) {
3431
            LOGGER.warn("Can't export.", ex);
3432
            status.message("Can't export");
3433
            status.abort();
3434
            if (target != null) {
3435
                target.cancelEditingQuietly();
3436
            }
3437
            if (entitiesStore != null) {
3438
                entitiesStore.cancelEditingQuietly();
3439
            }
3440
            return errcode;
3441
        } finally {
3442
            DisposeUtils.disposeQuietly(request);
3443
            if (target != null) {
3444
                this.removeStoreIgnoreChanges(target);
3445
            }
3446
            DisposeUtils.disposeQuietly(target);
3447
            DisposeUtils.disposeQuietly(entitiesStore);
3448

    
3449
        }
3450
    }
3451

    
3452
    @Override
3453
    public List<String> getDataModels() {
3454
        List<VCSGisEntity> rEntities = getRepositoryEntities();
3455
        Set<String> dataModels = new HashSet();
3456
        for (VCSGisEntity entity : rEntities) {
3457
            List<String> dataModelsEntity = entity.getDataModelsAsList();
3458
            dataModels.addAll(dataModelsEntity);
3459
        }
3460
        return new ArrayList<>(dataModels);
3461
    }
3462
}