Statistics
| Revision:

gvsig-projects-pool / org.gvsig.online / trunk / org.gvsig.online / org.gvsig.online.lib / org.gvsig.online.lib.impl / src / main / java / org / gvsig / online / lib / impl / workspace / tables / WorkspaceChangesTable.java @ 9512

History | View | Annotate | Download (36.5 KB)

1
package org.gvsig.online.lib.impl.workspace.tables;
2

    
3
import java.sql.Connection;
4
import java.sql.ResultSet;
5
import java.sql.SQLException;
6
import java.util.Iterator;
7
import java.util.List;
8
import javax.json.JsonObject;
9
import org.apache.commons.collections.CollectionUtils;
10
import org.apache.commons.lang3.StringUtils;
11
import org.gvsig.expressionevaluator.ExpressionBuilder;
12
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
13
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
14
import org.gvsig.expressionevaluator.ExpressionUtils;
15
import org.gvsig.fmap.dal.DALLocator;
16
import org.gvsig.fmap.dal.DataManager;
17
import static org.gvsig.fmap.dal.DataManager.RECOMENDED_SIZE_FOR_CLOB;
18
import org.gvsig.fmap.dal.DataTransaction;
19
import org.gvsig.fmap.dal.exception.DataException;
20
import org.gvsig.fmap.dal.feature.DisposableFeatureSetIterable;
21
import org.gvsig.fmap.dal.feature.EditableFeature;
22
import org.gvsig.fmap.dal.feature.EditableFeatureType;
23
import org.gvsig.fmap.dal.feature.Feature;
24
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
25
import org.gvsig.fmap.dal.feature.FeatureQuery;
26
import org.gvsig.fmap.dal.feature.FeatureSet;
27
import org.gvsig.fmap.dal.feature.FeatureStore;
28
import static org.gvsig.fmap.dal.feature.FeatureStore.MODE_PASS_THROUGH;
29
import org.gvsig.fmap.dal.feature.FeatureType;
30
import org.gvsig.fmap.dal.store.jdbc2.JDBCServerExplorer;
31
import org.gvsig.json.Json;
32
import org.gvsig.online.lib.api.workingcopy.OnlineEntity;
33
import org.gvsig.online.lib.api.OnlineManager;
34
import static org.gvsig.online.lib.api.OnlineManager.FEATURECODE_FIELD_NAME;
35
import static org.gvsig.online.lib.api.OnlineManager.ONLINECODELEN;
36
import static org.gvsig.online.lib.api.OnlineManager.OP_DELETE;
37
import static org.gvsig.online.lib.api.OnlineManager.OP_IGNORE;
38
import static org.gvsig.online.lib.api.OnlineManager.OP_INSERT;
39
import static org.gvsig.online.lib.api.OnlineManager.OP_UNKNOWN;
40
import static org.gvsig.online.lib.api.OnlineManager.OP_UPDATE;
41
import static org.gvsig.online.lib.api.OnlineManager.STATE_CONFLICT;
42
import static org.gvsig.online.lib.api.OnlineManager.STATE_LOCAL_MODIFIED;
43
import static org.gvsig.online.lib.api.OnlineManager.STATE_LOCAL_NEW;
44
import static org.gvsig.online.lib.api.OnlineManager.STATE_LOCAL_UNMODIFIED;
45
import org.gvsig.online.lib.api.OnlineRuntimeException;
46
import org.gvsig.online.lib.impl.OnlineUtils;
47
import org.gvsig.online.lib.impl.workspace.tables.RemoteChangesTable.RemoteChangeRow;
48
import org.gvsig.tools.dataTypes.DataTypes;
49
import org.gvsig.tools.dispose.DisposableIterable;
50
import org.gvsig.tools.dispose.DisposeUtils;
51
import org.gvsig.tools.dynobject.DynObjectValueItem;
52
import org.gvsig.tools.util.GetItemWithSize64;
53
import org.gvsig.tools.util.GetItemWithSizeAndIterator64;
54
import org.gvsig.online.lib.api.workingcopy.OnlineWorkingcopy;
55
import org.gvsig.online.lib.api.workingcopy.OnlineWorkingcopyChange;
56

    
57
/**
58
 *
59
 * @author gvSIG Team
60
 */
61
@SuppressWarnings("UseSpecificCatch")
62
public class WorkspaceChangesTable extends AbstractTable {
63

    
64
    
65
    public static final String TABLE_NAME = "ONLINE_WSCHANGES";
66
    
67
    public static final String COD_CHANGE = "COD_WSCHANGE";
68
    public static final String COD_ENTITY = "COD_ENTITY";
69
    public static final String SELECTED = "WSCH_SELECTED";
70
    public static final String FEATUREID = "WSCH_FEATURECODE";
71
    public static final String OPERATION = "WSCH_OPERATION";
72
    public static final String PREVIOUS_OPERATION = "WSCH_PREVOPERATION";
73
    public static final String STATUS = "WSCH_STATUS";
74
    private static final String FEATURE_DATA = "WSCH_DATA";
75
    private static final String EDITING_SESSION = "WSCH_EDITINGSESSION";
76

    
77
    private static final String LABEL = "WSCH_LABEL";
78
    private static final int MAX_SIZE_LABEL = 40;
79

    
80
    @SuppressWarnings("UseSpecificCatch")
81
    public static class WorkspaceChangeRow extends AbstractRow implements OnlineWorkingcopyChange {
82

    
83
        protected OnlineEntity entity;
84
        
85
        public WorkspaceChangeRow(OnlineWorkingcopy workspace) {
86
            this(workspace, null);
87
            setStatus(OnlineManager.STATE_LOCAL_UNMODIFIED);
88
        }
89
        
90
        public WorkspaceChangeRow(OnlineWorkingcopy workspace, Feature feature) {
91
            super(workspace, TABLE_NAME, COD_CHANGE, feature);
92
        }
93
        
94
        @Override
95
        public String getEntityCode() {
96
            return this.getString(COD_ENTITY);
97
        }
98

    
99
        @Override
100
        public long getRelatedFeatureCode() {
101
            return this.getLong(FEATUREID);
102
        }
103
        
104
        @Override
105
        public int getOperation() {
106
            return this.getInt(OPERATION);
107
        }
108
        
109
        @Override
110
        public String getOperationLabel() {
111
            return this.getLabelOfValue(OPERATION);
112
        }
113
        
114
        @Override
115
        public String getLabel() {
116
            return this.getString(LABEL);
117
        }
118

    
119
        @Override
120
        public boolean isSelected() {
121
            return this.getBoolean(SELECTED);
122
        }
123
        
124
        public void setEntityCode(String code) {
125
            this.set(COD_ENTITY, code);
126
        }
127

    
128
        public void setFeatureCode(long code) {
129
            this.set(FEATUREID, code);
130
        }
131
        
132
        public void setOperation(int op) {
133
            this.set(OPERATION, op);
134
        }
135
        
136
        public void setStatus(int status) {
137
            this.set(STATUS, status);
138
        }
139
        
140
        @Override
141
        public void setSelected(boolean selected) {
142
            this.set(SELECTED, selected);
143
        }
144

    
145
        public void setLabel(String label) {
146
            this.set(LABEL, StringUtils.abbreviate(label, MAX_SIZE_LABEL));
147
        }
148
        
149
        @Override
150
        public String getRelatedFeatureData() {
151
            String entityName = "unknown";
152
            long code = 0;
153
            FeatureStore store = null;
154
            try {
155
                entityName = this.getEntity().getEntityName();
156
                code = this.getRelatedFeatureCode();
157
                store = workspace.getFeatureStore(entityName);
158
                Feature f = store.findFirst("\""+this.getEntity().getFeatureIdFieldName()+"\"="+code);
159
                if( f==null ) {
160
                    int op = this.getOperation();
161
                    if( op == OnlineManager.OP_INSERT || op == OnlineManager.OP_UPDATE ) {
162
                        LOGGER.warn("Can't retrieve feature data for an insert or update operation (ENT/VCSGISCODE='"+entityName+"/"+code+"')");
163
                        throw new RuntimeException("Feature ENT/VCSGISCODE='"+entityName+"/"+code+"'not found.");
164
                    }
165
                    return ""; //null;
166
//                    throw new RuntimeException("Feature '"+entityName+"/"+code+"'not found.");
167
                }
168
                JsonObject json = f.toJson();
169
//                JsonObject json = f.toJson(Collections.singletonMap("geometryformat", this.workspace.getGeometryFormat()));
170
                String data = json.toString();
171
                return data;
172
            } catch (Exception ex) {
173
                LOGGER.warn("Can't retrieve feature data (ENT/ONLINECODE='"+entityName+"/"+code+"')");
174
                throw new RuntimeException("Can't retrieve feature data of ENT/ONLINECODE='"+entityName+"/"+code+"'.",ex);
175
            } finally {
176
                DisposeUtils.disposeQuietly(store);
177
            }
178
        }    
179

    
180
        @Override
181
        public JsonObject getRelatedFeatureDataAsJson() {
182
            String s = this.getRelatedFeatureData();
183
            return Json.createObject(s);
184
        }
185
        
186
        @Override
187
        public String toString() {
188
            switch (this.getOperation()) {
189
//                case OnlineManager.OP_ADD_ENTITY:
190
//                    return "{ OP:'ADD_ENTITY', ENTITYCODE:'"+this.getEntityCode()+"', }";
191
                case OnlineManager.OP_INSERT:
192
                    return "{ OP:'INSERT', ENTITYCODE:'"+this.getEntityCode()+"', FEATURECODE:'"+this.getRelatedFeatureCode()+"', DATA:'"+this.getRelatedFeatureData()+"' }";
193
                case OnlineManager.OP_UPDATE:
194
                    return "{ OP:'UPDATE', ENTITYCODE:'"+this.getEntityCode()+"', FEATURECODE:'"+this.getRelatedFeatureCode()+"', DATA:'"+this.getRelatedFeatureData()+"' }";
195
                case OnlineManager.OP_DELETE:
196
                    return "{ OP:'DELETE', ENTITYCODE:'"+this.getEntityCode()+"', FEATURECODE:'"+this.getRelatedFeatureCode()+"' }";
197
                default:
198
                    return "{ OP:'"+this.getOperation()+"', ENTITYCODE:'"+this.getEntityCode()+"', FEATURECODE:'"+this.getRelatedFeatureCode()+"' }";
199
            }
200
        }
201
        
202
        @Override
203
        public Feature getRelatedFeature() {
204
            Feature f = this.workspace.getRelatedFeature(this.getEntity(), this.getRelatedFeatureCode());
205
            if (f == null) {
206
                throw new RuntimeException("Feature '" + this.getEntity().getEntityName() + "/" + this.getRelatedFeatureCode() + "'not found.");
207
            }
208
            return f;
209
        }        
210

    
211
        public OnlineEntity getEntity() {
212
            if( this.entity == null ) {
213
                this.entity = this.workspace.getWorkspaceEntityByCode(this.getEntityCode());
214
            }
215
            return this.entity;
216
        }
217

    
218
        @Override
219
        public int getStatus() {
220
            return this.getInt(STATUS);
221
        }
222
        
223
        @Override
224
        public void update(FeatureStore store) {
225
            this.updateStatus();
226
            super.update(store);
227
        }
228

    
229
        @Override
230
        public void insert(FeatureStore store) {
231
            this.updateStatus();
232
            super.insert(store);
233
        }
234

    
235
        private void updateStatus() {
236
            if(getStatus() == OnlineManager.STATE_LOCAL_UNMODIFIED){
237
                switch(this.getOperation()){
238
                    case OnlineManager.OP_INSERT:
239
//                    case OnlineManager.OP_ADD_ENTITY:
240
                        setStatus(OnlineManager.STATE_LOCAL_NEW);
241
                        return;
242
                    case OnlineManager.OP_DELETE:
243
                    case OnlineManager.OP_UPDATE:
244
                        setStatus(OnlineManager.STATE_LOCAL_MODIFIED);
245
                        return;
246
                }
247
            }
248
        }
249
        
250
        public void revert(FeatureStore userStore, FeatureStore changesStore) throws DataException {
251
            long code = this.getRelatedFeatureCode();
252
            EditableFeature editable;
253
            switch (this.getOperation()) {
254
                case OnlineManager.OP_INSERT:
255
                    userStore.delete("\""+FEATURECODE_FIELD_NAME+"\" = "+code);
256
                    changesStore.delete("\""+COD_CHANGE+"\" = '"+this.getCode()+"'");
257
                    break;
258
//                case OnlineManager.OP_ADD_ENTITY:
259
//                    break;
260
                case OnlineManager.OP_UPDATE:
261
                    Feature feat = userStore.findFirst("\""+FEATURECODE_FIELD_NAME+"\" = "+code);
262
                    if(feat == null) {
263
                        throw new OnlineRuntimeException(1, "xxx");
264
                    }
265
                    editable = feat.getEditable();
266
                    editable.copyFrom(this.getDataAsJson());
267
                    userStore.update(editable);
268
                    changesStore.delete("\""+COD_CHANGE+"\" = '"+this.getCode()+"'");
269
                    break;
270
                case OnlineManager.OP_DELETE:
271
                    editable = userStore.createNewFeature(this.getDataAsJson());
272
                    userStore.insert(editable);
273
                    changesStore.delete("\""+COD_CHANGE+"\" = '"+this.getCode()+"'");
274
                    break;
275
            }
276
        }
277

    
278
        public void setData(String data) {
279
            this.set(FEATURE_DATA, data);
280
        }
281

    
282
        @Override
283
        public String getData() {
284
            return this.getString(FEATURE_DATA);
285
        }
286

    
287
        @Override
288
        public JsonObject getDataAsJson() {
289
            String s = this.getData();
290
            return Json.createObject(s);
291
        }
292

    
293
        public void setEditingSession(String editingSession) {
294
            this.set(EDITING_SESSION, editingSession);
295
        }
296

    
297
        public void setPreviousOperation(int operation) {
298
            this.set(PREVIOUS_OPERATION, operation);
299
        }
300
    }
301
    
302
    public WorkspaceChangesTable() {
303
        super(TABLE_NAME, featureType());
304
    }
305

    
306
    public DisposableFeatureSetIterable getByOperation(OnlineWorkingcopy workspace, int op) {
307
        return getByOperation(workspace, null, op);
308
//        FeatureStore store = null;
309
//        try {
310
//            store = workspace.getFeatureStore(TABLE_NAME);
311
//            FeatureQuery query = store.createFeatureQuery();
312
//            query.addFilter("\""+WorkspaceChangesTable.OPERATION+"\"="+op);
313
//            query.retrievesAllAttributes();
314
//            DisposableFeatureSetIterable changes = store.getFeatureSet(query).iterable();
315
//            return changes;
316
//        } catch (Exception ex) {
317
//            throw new RuntimeException("Can't retrieve changes for operartion "+op+".", ex);
318
//        } finally {
319
//            if( store!=null ) {
320
//                DisposeUtils.dispose(store);
321
//            }
322
//        }
323
    }
324

    
325
    public DisposableFeatureSetIterable getByOperation(OnlineWorkingcopy workspace, String entityCode, int op) {
326
        FeatureStore store = null;
327
        try {
328
            store = workspace.getFeatureStore(TABLE_NAME);
329
            FeatureQuery query = store.createFeatureQuery();
330
            if( !StringUtils.isBlank(entityCode) ) {
331
                query.addFilter("\""+COD_ENTITY+"\" ='"+entityCode+"' AND \""+WorkspaceChangesTable.OPERATION+"\"="+op);
332
            } else {
333
                query.addFilter("\""+WorkspaceChangesTable.OPERATION+"\"="+op);
334
            }
335
            
336
            query.retrievesAllAttributes();
337
            DisposableFeatureSetIterable changes = store.getFeatureSet(query).iterable();
338
            return changes;
339
        } catch (Exception ex) {
340
            throw new RuntimeException("Can't retrieve changes for operartion "+op+".", ex);
341
        } finally {
342
            if( store!=null ) {
343
                DisposeUtils.dispose(store);
344
            }
345
        }
346
    }
347
    
348
    
349
    public DisposableFeatureSetIterable getGroupedByEntity(OnlineWorkingcopy workspace) {
350
        FeatureStore store = null;
351
        try {
352
            store = workspace.getFeatureStore(TABLE_NAME);
353
            FeatureQuery query = store.createFeatureQuery();
354

    
355
            query.getOrder().add(WorkspaceChangesTable.COD_ENTITY,true);
356
            query.getGroupByColumns().add(WorkspaceChangesTable.COD_ENTITY);
357
            query.getAggregateFunctions().put(SELECTED, "MAX");
358
            query.retrievesAllAttributes();
359
            DisposableFeatureSetIterable changes = store.getFeatureSet(query).iterable();
360
            return changes;
361
        } catch (Exception ex) {
362
            throw new RuntimeException("Can't retrieve changes grouped by entity.", ex);
363
        } finally {
364
            if( store!=null ) {
365
                DisposeUtils.dispose(store);
366
            }
367
        }
368
    }
369

    
370
//    public DisposableFeatureSetIterable getSelectedsWithoutAddEntity(OnlineWorkingcopy workspace) {
371
//        return getSelectedsWithoutAddEntity(workspace, null);
372
//    }
373
//    
374
//    public DisposableFeatureSetIterable getSelectedsWithoutAddEntity(OnlineWorkingcopy workspace, List<String> entityCodes) {
375
//        FeatureStore store = null;
376
//        try {
377
//            store = workspace.getFeatureStore(TABLE_NAME);
378
//            FeatureQuery query = store.createFeatureQuery();
379
//
380
//            if(CollectionUtils.isEmpty(entityCodes)){
381
//                query.setFilter("\""+SELECTED+"\" AND \""
382
////                    +OPERATION+"\" <> "+OnlineManager.OP_ADD_ENTITY+" AND \""
383
//                    +OPERATION+"\" <> "+OnlineManager.OP_IGNORE);
384
//            } else {
385
//                ExpressionBuilder expBuilder = ExpressionUtils.createExpressionBuilder();
386
//                for (String entityCode : entityCodes) {
387
//                    expBuilder.or(expBuilder.eq(expBuilder.column(COD_ENTITY), expBuilder.constant(entityCode)));
388
//                }
389
//                expBuilder.and(expBuilder.column(SELECTED))
390
////                        .and(expBuilder.ne(expBuilder.column(OPERATION), expBuilder.constant(OnlineManager.OP_ADD_ENTITY)))
391
//                        .and(expBuilder.ne(expBuilder.column(OPERATION), expBuilder.constant(OnlineManager.OP_IGNORE)));
392
//                query.setFilter(expBuilder.value().toString());
393
//            }
394
//            
395
//            query.retrievesAllAttributes();
396
//            DisposableFeatureSetIterable changes = store.getFeatureSet(query).iterable();
397
//            if( changes.isEmpty() ) {
398
//                DisposeUtils.disposeQuietly(changes);
399
//                return null;
400
//            }
401
//            return changes;
402
//        } catch (Exception ex) {
403
//            throw new RuntimeException("Can't retrieve all changes.", ex);
404
//        } finally {
405
//           DisposeUtils.disposeQuietly(store);
406
//        }
407
//    }
408
    
409
    public DisposableFeatureSetIterable getAll(OnlineWorkingcopy workspace) {
410
        FeatureStore store = null;
411
        try {
412
            store = workspace.getFeatureStore(TABLE_NAME);
413
            DisposableFeatureSetIterable changes = store.getFeatureSet().iterable();
414
            return changes;
415
        } catch (Exception ex) {
416
            throw new RuntimeException("Can't retrieve all changes.", ex);
417
        } finally {
418
            DisposeUtils.disposeQuietly(store);
419
        }
420
    }
421

    
422
    public GetItemWithSize64<Feature> getByEntityCode(OnlineWorkingcopy workspace, List<OnlineEntity> entities) {
423
        FeatureStore store = null;
424
        try {
425
            store = workspace.getFeatureStore(TABLE_NAME);
426
            if( CollectionUtils.isEmpty(entities) ) {
427
                GetItemWithSizeAndIterator64<Feature> changes = store.getFeatures64(
428
                        null, 
429
                        "\""+COD_ENTITY+"\",-\""+OPERATION+"\",\""+COD_CHANGE+"\"", 
430
                        true);
431
                return changes;
432
            }
433
            ExpressionBuilder exprBuilder = ExpressionUtils.createExpressionBuilder();
434
            for (OnlineEntity entity : entities) {
435
                exprBuilder.or(exprBuilder.eq(exprBuilder.column(COD_ENTITY), exprBuilder.constant(entity.getEntityCode())));
436
            }
437
            GetItemWithSizeAndIterator64<Feature> changes = store.getFeatures64(
438
                    exprBuilder.value().toString(),
439
                    "\""+COD_ENTITY+"\",-\""+OPERATION+"\",\""+COD_CHANGE+"\"", 
440
                    true
441
            );
442
            return changes;
443
        } catch (Exception ex) {
444
            throw new RuntimeException("Can't retrieve changes by entity.", ex);
445
        } finally {
446
           DisposeUtils.disposeQuietly(store);
447
        }
448
    }
449
    
450
    public boolean hasLocalChangesByEntityCode(OnlineWorkingcopy workspace, List<OnlineEntity> entities) {
451
        FeatureStore store = null;
452
        try {
453
            store = workspace.getFeatureStore(TABLE_NAME);
454
            if( CollectionUtils.isEmpty(entities) ) {
455
                Feature f = store.findFirst((FeatureQuery)null);
456
                return f!=null;
457
            }
458
            ExpressionBuilder exprBuilder = ExpressionUtils.createExpressionBuilder();
459
            for (OnlineEntity entity : entities) {
460
                exprBuilder.or(exprBuilder.eq(exprBuilder.column(COD_ENTITY), exprBuilder.constant(entity.getEntityCode())));
461
            }
462
            Feature f = store.findFirst(exprBuilder.value().toString());
463
            return f!=null;
464
        } catch (Exception ex) {
465
            throw new RuntimeException("Can't retrieve changes by entity.", ex);
466
        } finally {
467
           DisposeUtils.disposeQuietly(store);
468
        }
469
    }
470

    
471
    public long getCountLocalChangesOfEntity(OnlineWorkingcopy workspace, String entityCode) {
472
        return this.getCountLocalChangesOfEntity(workspace, null, entityCode);
473
    }
474
    
475
    public long getCountLocalChangesOfEntity(OnlineWorkingcopy workspace, DataTransaction transaction, String entityCode) {
476
        FeatureStore store = null;
477
        FeatureSet changes = null;
478
        try {
479
            if( transaction==null ) {
480
                store = workspace.getFeatureStore(TABLE_NAME);
481
            } else {
482
                store = transaction.getFeatureStore(TABLE_NAME);
483
                if( store == null ) {
484
                    store = workspace.getFeatureStore(TABLE_NAME);
485
                } else {
486
                    DisposeUtils.bind(store);
487
                }
488
            }
489
            if( StringUtils.isBlank(entityCode) ) {
490
                throw new IllegalArgumentException("entityCode is required.");
491
            }
492
            changes = store.getFeatureSet(
493
                    "\""+COD_ENTITY+"\"='"+entityCode+"'"
494
            );
495
            return changes.size64();
496
        } catch (Exception ex) {
497
            throw new RuntimeException("Can't retrieve changes by entity.", ex);
498
        } finally {
499
            DisposeUtils.disposeQuietly(changes);
500
            DisposeUtils.disposeQuietly(store);
501
        }
502
    }
503

    
504
    public WorkspaceChangeRow getByEntityAndDataCode(
505
            OnlineWorkingcopy workspace, 
506
            String entityCode, 
507
            String featureCode,
508
            FeatureStore localChangesStore
509
        ) {
510
        FeatureStore store = localChangesStore;
511
        try {
512
            if(store == null){
513
                store = workspace.getFeatureStore(TABLE_NAME);
514
            }
515
            Feature f = store.findFirst(
516
                    "\"" + COD_ENTITY + "\"='" + entityCode + "' AND \""+FEATUREID+"\"='"+featureCode+"'"
517
            );
518
            if (f == null) {
519
                return null;
520
            }
521
            WorkspaceChangeRow row = new WorkspaceChangeRow(workspace, f);
522
            return row;
523
        } catch (Exception ex) {
524
            throw new RuntimeException("Can't retrieve change for 'FEATURECODE[" + featureCode + "]'.", ex);
525
        } finally {
526
            if(localChangesStore == null){
527
                DisposeUtils.disposeQuietly(store);
528
            }
529
        }
530
    }
531

    
532
    public void deleteAll(OnlineWorkingcopy workspace) {
533
        FeatureStore store = null;
534
        try {
535
            store = workspace.openFeatureStore(TABLE_NAME, true);
536
            store.edit(MODE_PASS_THROUGH);
537
            store.delete("TRUE");
538
            store.finishEditing();
539
        } catch (Exception ex) {
540
            FeatureStore.cancelEditingQuietly(store);
541
            throw new RuntimeException("Can't delete all changes.", ex);
542
        } finally {
543
            if( store!=null ) {
544
                DisposeUtils.dispose(store);
545
            }
546
        }
547
    }
548

    
549
    public void deleteSelecteds(OnlineWorkingcopy workspace, List<String> entityCodes) {
550
        FeatureStore store = null;
551
        try {
552
            store = workspace.openFeatureStore(TABLE_NAME, true);
553
            store.edit(MODE_PASS_THROUGH);
554
            ExpressionBuilder expBuilder = ExpressionUtils.createExpressionBuilder();
555
            if(CollectionUtils.isNotEmpty(entityCodes)){
556
                for (String entityCode : entityCodes) {
557
                    expBuilder.or(expBuilder.eq(expBuilder.column(COD_ENTITY), expBuilder.constant(entityCode)));
558
                }
559
            }
560
            expBuilder.and(expBuilder.column(SELECTED));
561
            
562
            store.delete(expBuilder.value().toString());
563
            store.finishEditing();
564
        } catch (Exception ex) {
565
            FeatureStore.cancelEditingQuietly(store);
566
            throw new RuntimeException("Can't delete selected changes.", ex);
567
        } finally {
568
            if( store!=null ) {
569
                DisposeUtils.dispose(store);
570
            }
571
        }
572
    }
573

    
574
    public void deleteByEntity(OnlineWorkingcopy workspace, String entityCode) {
575
        FeatureStore store = null;
576
        try {
577
            store = workspace.openFeatureStore(TABLE_NAME, true);
578
            store.edit(MODE_PASS_THROUGH);
579
            store.delete("\""+COD_ENTITY+"\"='"+entityCode+"'");
580
            store.finishEditing();
581
        } catch (Exception ex) {
582
            FeatureStore.cancelEditingQuietly(store);
583
            throw new RuntimeException("Can't delete selected changes.", ex);
584
        } finally {
585
            if( store!=null ) {
586
                DisposeUtils.dispose(store);
587
            }
588
        }
589
    }
590
    
591
        public DisposableFeatureSetIterable getSelectedsByEntityCodeAsIterator(OnlineWorkingcopy workspace, String entityCode) {
592
        FeatureStore store = null;
593
        try {
594
            store = workspace.getFeatureStore(TABLE_NAME);
595
            FeatureSet changes;
596
            if( StringUtils.isBlank(entityCode) ) {
597
                changes = store.getFeatureSet("\""+SELECTED+"\"");
598
            } else {
599
                changes = store.getFeatureSet("\""+SELECTED+"\" AND \""+COD_ENTITY+"\"='"+entityCode+"'");
600
            }
601
            return changes.iterable();
602
        } catch (Exception ex) {
603
            throw new RuntimeException("Can't retrieve selected remote changes by entity code (ENTITY["+entityCode+"]).", ex);
604
        } finally {
605
            if( store!=null ) {
606
                DisposeUtils.dispose(store);
607
            }
608
        }
609
    }
610

    
611

    
612
    public void deleteSelectedsByEntity(OnlineWorkingcopy workspace, String entityCode) {
613
        FeatureStore store = null;
614
        try {
615
            store = workspace.openFeatureStore(TABLE_NAME, true);
616
            store.edit(MODE_PASS_THROUGH);
617
            store.delete("\""+COD_ENTITY+"\"='"+entityCode+"'"+" AND "+"\""+SELECTED+"\"");
618
            store.finishEditing();
619
        } catch (Exception ex) {
620
            FeatureStore.cancelEditingQuietly(store);
621
            throw new RuntimeException("Can't delete selected changes.", ex);
622
        } finally {
623
            if( store!=null ) {
624
                DisposeUtils.dispose(store);
625
            }
626
        }
627
    }
628

    
629
    public WorkspaceChangeRow find(OnlineWorkingcopy workspace, FeatureStore store, String entityCode, long featureCode) {
630
        try {
631
            Feature f = store.findFirst(
632
//                    "\""+FEATUREID+"\"='"+featureCode+"'"
633
                    "\""+COD_ENTITY+"\"='"+entityCode+"' AND \""+FEATUREID+"\"="+featureCode
634
            );
635
            if(f==null){
636
                return null;
637
            }
638
            return new WorkspaceChangeRow(workspace, f);
639
        } catch (Exception ex) {
640
            throw new RuntimeException("Can't retrieve change.", ex);
641
        }
642
    }
643
    
644
    public static final FeatureType featureType() {
645
        DataManager dataManager = DALLocator.getDataManager();
646
        EditableFeatureType ft = dataManager.createFeatureType();
647
        ft.setLabel("Online Local changes");
648
        ft.getTags().set("ID", TABLE_NAME);
649
        ft.add(COD_CHANGE, DataTypes.STRING)
650
                .setSize(ONLINECODELEN)
651
                .setIsPrimaryKey(true)
652
                .setLabel("Code")
653
                .setReadOnly(false);        
654
        ft.add(COD_ENTITY, DataTypes.STRING)
655
//                .setIsIndexed(true)
656
                .setAllowIndexDuplicateds(true)
657
                .setSize(ONLINECODELEN)
658
                .setLabel("Entity code");
659
        ft.add(SELECTED, DataTypes.BOOLEAN)
660
//                .setIsIndexed(true)
661
                .setAllowIndexDuplicateds(true)
662
                .setLabel("Selected");
663
        ft.add(EDITING_SESSION, DataTypes.STRING)
664
                .setIsIndexed(true)
665
                .setAllowIndexDuplicateds(true)
666
                .setLabel("Editing session");
667
        ft.add(FEATUREID, DataTypes.LONG)
668
                .setIsIndexed(true)
669
                .setLabel("Identifier")
670
                .setDescription("The identifier of the feature");
671
        ft.add(OPERATION, DataTypes.INTEGER)
672
                .setIsIndexed(true)
673
                .setLabel("Operation")
674
                .setAvailableValues(new DynObjectValueItem[] {
675
//                    new DynObjectValueItem(OP_ADD_ENTITY, "Add entity"),
676
                    new DynObjectValueItem(OP_INSERT, "Insert"),
677
                    new DynObjectValueItem(OP_UPDATE, "Update"),
678
                    new DynObjectValueItem(OP_DELETE, "Delete"),
679
                    new DynObjectValueItem(OP_IGNORE, "Ignore")
680
                });
681
        ft.add(PREVIOUS_OPERATION, DataTypes.INTEGER)
682
                .setIsIndexed(true)
683
                .setLabel("Operation")
684
                .setAvailableValues(new DynObjectValueItem[] {
685
                    new DynObjectValueItem(OP_INSERT, "Insert"),
686
                    new DynObjectValueItem(OP_UPDATE, "Update"),
687
                    new DynObjectValueItem(OP_UNKNOWN, "Unknown")
688
                });
689
        ft.add(STATUS, DataTypes.INTEGER)
690
                .setLabel("Status")
691
                .setAvailableValues(new DynObjectValueItem[] {
692
                    new DynObjectValueItem(STATE_LOCAL_NEW, "New"),
693
                    new DynObjectValueItem(STATE_LOCAL_UNMODIFIED, "Unmodified"),
694
                    new DynObjectValueItem(STATE_LOCAL_MODIFIED, "Modified"),
695
                    new DynObjectValueItem(STATE_CONFLICT, "Conflict")
696
                });
697
        ft.add(LABEL, DataTypes.STRING)
698
                .setIsIndexed(false)
699
                .setSize(MAX_SIZE_LABEL)
700
                .setLabel("Label")
701
                .setDescription("The label of the feature");
702
        ft.add(FEATURE_DATA, DataTypes.STRING)
703
                .setSize(RECOMENDED_SIZE_FOR_CLOB)
704
                .setLabel("Data");
705
        
706
        return ft.getNotEditableCopy();
707
    }
708
    
709
    public void removeLocalChangesRelatedToSelectedRemoteChanges(OnlineWorkingcopy workspace, OnlineEntity lentity) {
710
        String sql = String.format(OnlineUtils.getSqlTemplate(workspace.getExplorer().getProviderName(), "removeLocalChangesRelatedToSelectedRemoteChanges"), lentity.getEntityCode());
711
        Object res = workspace.getExplorer().execute(sql);
712
    }
713

    
714
    public void removeLocalChanges(OnlineWorkingcopy workspace, OnlineEntity lentity, String editingSession) {
715
        FeatureStore store = null;
716
        try {
717
            store = workspace.openFeatureStore(TABLE_NAME, true);
718
            store.edit(FeatureStore.MODE_PASS_THROUGH);
719
            store.delete("\""+EDITING_SESSION+"\" = '"+editingSession+"'");
720
            store.finishEditingQuietly();
721
        } catch (Exception ex) {
722
            FeatureStore.cancelEditingQuietly(store);
723
            throw new RuntimeException("Can't remove local changes.", ex);
724
        } finally {
725
            DisposeUtils.disposeQuietly(store);
726
        }
727
    }
728

    
729
    public void revertChangedLocalChanges(OnlineWorkingcopy workspace, OnlineEntity lentity, String editingSession) {
730
        FeatureStore store = null;
731
        FeatureSet features = null;
732
        try {
733
            store = workspace.openFeatureStore(TABLE_NAME, true);
734
            store.edit(FeatureStore.MODE_PASS_THROUGH);
735
            features = store.getFeatureSet("\""+EDITING_SESSION+"\" = '"+editingSession+"' and \""+PREVIOUS_OPERATION+"\" <> "+OP_UNKNOWN);
736
            for (Feature feature : features) {
737
                EditableFeature eFeature = feature.getEditable();
738
                eFeature.set(OPERATION, eFeature.get(PREVIOUS_OPERATION));
739
                eFeature.set(PREVIOUS_OPERATION, OP_UNKNOWN);
740
                store.update(eFeature);
741
            }
742
            store.finishEditingQuietly();
743
        } catch (Exception ex) {
744
            FeatureStore.cancelEditingQuietly(store);
745
            throw new RuntimeException("Can't remove local changes.", ex);
746
        } finally {
747
            DisposeUtils.disposeQuietly(features);
748
            DisposeUtils.disposeQuietly(store);
749
        }
750
    };
751

    
752
    public void removeIgnoredLocalChanges(OnlineWorkingcopy workspace, OnlineEntity lentity, String editingSession) {
753
        FeatureStore store = null;
754
        try {
755
            store = workspace.openFeatureStore(TABLE_NAME, true);
756
            store.edit(FeatureStore.MODE_PASS_THROUGH);
757
            store.delete("\""+EDITING_SESSION+"\" = '"+editingSession+"' and \""+OPERATION+"\" = "+OP_IGNORE);
758
            store.finishEditingQuietly();
759
        } catch (Exception ex) {
760
            FeatureStore.cancelEditingQuietly(store);
761
            throw new RuntimeException("Can't remove local changes.", ex);
762
        } finally {
763
            DisposeUtils.disposeQuietly(store);
764
        }
765
    };
766

    
767
    public DisposableIterable<WorkspaceChangeRow> getChangesWidthUserData(OnlineWorkingcopy workspace, OnlineEntity lentity, RemoteChangeRow remoteChange, FeatureStore localChangesStore, DataTransaction transaction) {
768

    
769
        FeatureType featType = lentity.getFeatureType();
770
        JsonObject data = remoteChange.getRelatedFeatureDataAsJson();
771
        ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
772
        ExpressionBuilder builder = expManager.createExpressionBuilder();
773
        builder.set(null);
774
        for (FeatureAttributeDescriptor attr : featType) {
775
            if(StringUtils.equalsAnyIgnoreCase(lentity.getFeatureIdFieldName(),attr.getName())){
776
                continue;
777
            }
778
            if(attr.isIndexed() && !attr.allowIndexDuplicateds()){
779
                Object value = Json.toObject(data, attr.getName());
780
                builder.or(
781
                    builder.eq(
782
                        builder.column(attr.getName()), 
783
                        builder.constant(value)
784
                    )
785
                );
786
            }
787
        }
788
        ExpressionBuilder.Value value = builder.value();
789
        if(value == null){
790
            return null;
791
        }
792
        
793
        JDBCServerExplorer serverExplorer = workspace.getExplorer(); 
794
        String sql = String.format(
795
                OnlineUtils.getSqlTemplate(
796
                        workspace.getExplorer().getProviderName(), 
797
                        "getChangesWidthUserData"
798
                ), 
799
                lentity.getEntityName(),
800
                lentity.getFeatureIdFieldName(),
801
                remoteChange.getRelatedFeatureCode(),
802
                builder.toString()
803
                );
804

    
805
        final ResultSet rs = (ResultSet) serverExplorer.execute(sql);
806
        if(rs == null){
807
            return null;
808
        }
809
        final WorkspaceChangeRow row;
810
        try {
811
            row = new WorkspaceChangeRow(workspace, localChangesStore.createNewFeature());
812
        } catch (DataException ex) {
813
            try {
814
                rs.close();
815
            } catch (SQLException ex2) {
816
            }
817
            return null;
818
        }
819
        DisposableIterable<WorkspaceChangeRow> r = new DisposableIterable<WorkspaceChangeRow>() {
820
            @Override
821
            public Iterator<WorkspaceChangeRow> iterator() {
822
                Iterator<WorkspaceChangeRow> it = new Iterator<WorkspaceChangeRow>() {
823
                    @Override
824
                    public boolean hasNext() {
825
                        try {
826
                            return rs.next();
827
                        } catch (SQLException ex) {
828
                            return false;
829
                        }
830
                    }
831

    
832
                    @Override
833
                    public WorkspaceChangeRow next() {
834
                        try {
835
                            row.setCode(rs.getString(COD_CHANGE));
836
                            row.setEntityCode(rs.getString(COD_ENTITY));
837
                            row.setFeatureCode(rs.getLong(FEATUREID));
838
                            row.setLabel(rs.getString(LABEL));
839
                            row.setOperation(rs.getInt(OPERATION));
840
                            row.setSelected(rs.getBoolean(SELECTED));
841
                            row.setStatus(rs.getInt(STATUS));
842
                            return row;
843
                        } catch (SQLException ex) {
844
                            return null;
845
                        }
846
                    }
847
                };
848
                return it;
849
            }
850

    
851
            @Override
852
            public void dispose() {
853
                try {
854
                    Connection conn = rs.getStatement().getConnection();
855
                    rs.close();
856
                    if(transaction != null && transaction.contains(serverExplorer) && transaction.isInProgress()){
857
                        return;
858
                    } 
859
                    conn.close();
860
                } catch (SQLException ex) {
861
                    LOGGER.warn("Can't close resultSet.", ex);
862
                }
863
            }
864
        };
865
        
866
        return r;
867
    }
868

    
869
    public void changeState(FeatureStore localChangesStore, String entityCode, int searchState, int replaceState) {
870
        try {
871
            boolean needFinish = false;
872
            if(localChangesStore.getMode() == FeatureStore.MODE_QUERY){
873
                localChangesStore.edit(MODE_PASS_THROUGH);
874
                needFinish = true;
875
            }
876
            String filter = "\""+COD_ENTITY+"\"='"+entityCode+"' AND \""+STATUS+"\"="+searchState;
877
            localChangesStore.update(STATUS,replaceState,filter);
878
            if(needFinish) {
879
                localChangesStore.finishEditing();
880
            }
881
        } catch (Exception ex) {
882
            throw new RuntimeException("Can't change state.", ex);
883
        }
884
    }
885

    
886
    
887
}