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 / RemoteChangesTable.java @ 9512

History | View | Annotate | Download (20.7 KB)

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

    
3
import java.sql.Timestamp;
4
import java.util.List;
5
import javax.json.JsonObject;
6
import javax.json.JsonString;
7
import javax.json.JsonValue;
8
import org.apache.commons.lang3.ArrayUtils;
9
import org.apache.commons.lang3.StringUtils;
10
import org.gvsig.expressionevaluator.ExpressionBuilder;
11
import org.gvsig.fmap.dal.DALLocator;
12
import org.gvsig.fmap.dal.DataManager;
13
import static org.gvsig.fmap.dal.DataManager.RECOMENDED_SIZE_FOR_CLOB;
14
import org.gvsig.fmap.dal.DataTransaction;
15
import org.gvsig.fmap.dal.feature.DisposableFeatureSetIterable;
16
import org.gvsig.fmap.dal.feature.EditableFeatureType;
17
import org.gvsig.fmap.dal.feature.Feature;
18
import org.gvsig.fmap.dal.feature.FeatureQuery;
19
import org.gvsig.fmap.dal.feature.FeatureSet;
20
import org.gvsig.fmap.dal.feature.FeatureStore;
21
import static org.gvsig.fmap.dal.feature.FeatureStore.MODE_PASS_THROUGH;
22
import org.gvsig.fmap.dal.feature.FeatureType;
23
import org.gvsig.fmap.geom.Geometry;
24
import org.gvsig.fmap.geom.GeometryLocator;
25
import org.gvsig.fmap.geom.GeometryManager;
26
import org.gvsig.json.Json;
27
import static org.gvsig.online.lib.api.OnlineManager.ONLINECODELEN;
28
import static org.gvsig.online.lib.api.OnlineManager.OP_DELETE;
29
import static org.gvsig.online.lib.api.OnlineManager.OP_INSERT;
30
import static org.gvsig.online.lib.api.OnlineManager.OP_UPDATE;
31
import static org.gvsig.online.lib.api.OnlineManager.STATE_CONFLICT;
32
import static org.gvsig.online.lib.api.OnlineManager.STATE_LOCAL_MODIFIED;
33
import static org.gvsig.online.lib.api.OnlineManager.STATE_LOCAL_UNMODIFIED;
34
import org.gvsig.online.lib.api.workingcopy.OnlineEntity;
35
import org.gvsig.online.lib.api.workingcopy.OnlineRemoteChange;
36
import org.gvsig.online.lib.api.workingcopy.OnlineWorkingcopy;
37
import org.gvsig.online.lib.impl.OnlineUtils;
38
import org.gvsig.tools.dataTypes.DataTypes;
39
import org.gvsig.tools.dispose.DisposeUtils;
40
import org.gvsig.tools.dynobject.DynObjectValueItem;
41
import org.gvsig.tools.util.GetItemWithSize64;
42

    
43
/**
44
 *
45
 * @author gvSIG Team
46
 */
47
@SuppressWarnings("UseSpecificCatch")
48
public class RemoteChangesTable extends AbstractTable {
49

    
50
    
51
    public static final String TABLE_NAME = "ONLINE_REMOTECHANGES";
52
    
53
    private static final String COD_REMOTECHANGE = "COD_REMOTECHANGE";
54
    public static final String COD_ENTITY = "COD_ENTITY";
55
    public static final String SELECTED = "RCH_SELECTED";
56
    private static final String FEATUREID = "RCH_FEATURECODE";
57
    private static final String REVISION_NUMBER = "RCH_REVNUMBER";
58
    private static final String OPERATION = "RCH_OPERATION";
59
    private static final String REVISION_DATE = "RCH_DATE";
60
    private static final String FEATURE_DATA = "RCH_DATA";
61
    private static final String STATUS = "RCH_STATUS";
62
  
63
    @SuppressWarnings("UseSpecificCatch")
64
    public static class RemoteChangeRow extends AbstractRow implements OnlineRemoteChange {
65

    
66
        protected OnlineEntity entity;
67
        
68
        public RemoteChangeRow(OnlineWorkingcopy workspace) {
69
            super(workspace, TABLE_NAME, COD_REMOTECHANGE);
70
        }
71
        
72
        public RemoteChangeRow(OnlineWorkingcopy workspace, Feature feature) {
73
            super(workspace, TABLE_NAME, COD_REMOTECHANGE, feature);
74
        }
75
        
76
        @Override
77
        public String getEntityCode() {
78
            return this.getString(COD_ENTITY);
79
        }
80

    
81
        @Override
82
        public long getRelatedFeatureCode() {
83
            if( this.isNull(FEATUREID)){
84
                return 0l;
85
            }
86
            return this.getLong(FEATUREID);
87
        }
88

    
89
        private Feature getRelatedFeature() {
90
            String entityName;
91
            long code;
92
            FeatureStore store = null;
93
            try {
94
                entityName = this.getEntity().getEntityName();
95
                code = this.getRelatedFeatureCode();
96
                store = workspace.getFeatureStore(entityName);
97
                Feature f = store.findFirst("\""+this.getEntity().getFeatureIdFieldName()+"\"="+code);
98
                if( f==null ) {
99
                    return null;
100
                }
101
                return f;
102
            } catch (Exception ex) {
103
                return null;
104
            } finally {
105
                DisposeUtils.disposeQuietly(store);
106
            }
107
        }        
108
        
109
        @Override
110
        public long getRevisionNumber() {
111
            return this.getLong(REVISION_NUMBER);
112
        }
113
        
114
        @Override
115
        public Timestamp getRevisionDate() {
116
            return this.getTimestamp(REVISION_DATE);
117
        }
118
        
119
        @Override
120
        public int getOperation() {
121
            return this.getInt(OPERATION);
122
        }
123
        
124
        @Override
125
        public String getOperationLabel() {
126
            return OnlineUtils.getOperationLabel(this.getOperation());
127
        }
128
        
129
        @Override
130
        public boolean isSelected() {
131
            return this.getBoolean(SELECTED);
132
        }
133
        
134
        @Override
135
        public int getStatus() {
136
            return this.getInt(STATUS);
137
        }
138
        
139
        @Override
140
        public String getRelatedFeatureData() {
141
            return this.getString(FEATURE_DATA);
142
        }        
143

    
144
        @Override
145
        public JsonObject getRelatedFeatureDataAsJson() {
146
            JsonObject json = Json.createObject(this.getString(FEATURE_DATA));
147
            return json;
148
        }        
149

    
150
        public void setEntityCode(String code) {
151
            this.set(COD_ENTITY, code);
152
        }
153

    
154
//        public void setUserCode(String code) {
155
//            this.feature.set(COD_USER, code);
156
//        }
157

    
158
        public void setData(String data) {
159
            this.set(FEATURE_DATA, data);
160
        }
161

    
162
        public void setRevisionNumber(long revnum) {
163
            this.set(REVISION_NUMBER, revnum);
164
        }
165

    
166
        public void setEfectiveDate(Timestamp date) {
167
            this.set(REVISION_DATE, date);
168
        }
169

    
170
        public void setRelatedFeatureCode(long code) {
171
            this.set(FEATUREID, code);
172
        }
173
        
174
        public void setOperation(int op) {
175
            this.set(OPERATION, op);
176
        }
177
        
178
        @Override
179
        public void setSelected(boolean selected) {
180
            this.set(SELECTED, selected);
181
        }
182
        
183
        public void setStatus(int status) {
184
            this.set(STATUS, status);
185
        }
186
        
187
        public OnlineEntity getEntity() {
188
            if( this.entity == null ) {
189
                this.entity = this.workspace.getWorkspaceEntityByCode(this.getEntityCode());
190
            }
191
            return this.entity;
192
        }
193

    
194
        @Override
195
        public String getLabel() {
196
            if(StringUtils.isBlank(this.getRelatedFeatureData())){
197
                Feature f = getRelatedFeature();
198
                if(f==null){
199
                    return null;
200
                }
201
                return f.getString(this.getEntity().getFieldForLabel());
202
            }
203
            JsonValue jsonValue = this.getRelatedFeatureDataAsJson().get(this.getEntity().getFieldForLabel());
204
            return convertJsonValueToString(jsonValue);
205
        }
206
        
207
        private static String convertJsonValueToString(JsonValue jsonValue) {
208
            if( jsonValue==null ) {
209
                return "";
210
            }
211
            if (jsonValue instanceof JsonString) {
212
                String jsonString = jsonValue.toString();
213
                return jsonString.substring(1, jsonString.length() - 1);
214
            } else {
215
                return jsonValue.toString();
216
            }
217
        }
218
        
219
        @Override
220
        public String toString() {
221
            switch (this.getOperation()) {
222
                case OP_INSERT:
223
                    return "{ OP:'INSERT', ENTITYCODE:'"+this.getEntityCode()+"', FEATURECODE:'"+this.getRelatedFeatureCode()+"', DATA:'"+this.getRelatedFeatureData()+"' }";
224
                case OP_UPDATE:
225
                    return "{ OP:'UPDATE', ENTITYCODE:'"+this.getEntityCode()+"', FEATURECODE:'"+this.getRelatedFeatureCode()+"', DATA:'"+this.getRelatedFeatureData()+"' }";
226
                case OP_DELETE:
227
                    return "{ OP:'DELETE', ENTITYCODE:'"+this.getEntityCode()+"', FEATURECODE:'"+this.getRelatedFeatureCode()+"' }";
228
                default:
229
                    return "{ OP:'"+this.getOperation()+"', ENTITYCODE:'"+this.getEntityCode()+"', FEATURECODE:'"+this.getRelatedFeatureCode()+"' }";
230
            }
231
        }
232
        
233
        @Override
234
        public Geometry getGeometry() {
235
            Geometry geom = null;
236
            GeometryManager geometryManager = GeometryLocator.getGeometryManager();
237
            String geometryFieldName = getEntity().getGeometryFieldName();
238
            String data = getRelatedFeatureData();
239
            if( !StringUtils.isBlank(data) && !StringUtils.isBlank(geometryFieldName) ) {
240
                JsonObject dataJson = Json.createObject(data);
241
                geom = geometryManager.createFromQuietly(
242
                        dataJson.getString(geometryFieldName, null)
243
                );
244
            }
245
            return geom;
246
        }
247

    
248
    }
249
    
250
    public RemoteChangesTable() {
251
        super(TABLE_NAME, featureType());
252
    }
253

    
254

    
255
    public void deleteAll(OnlineWorkingcopy workspace) {
256
        FeatureStore store = null;
257
        try {
258
            store = workspace.getFeatureStore(TABLE_NAME);
259
            store.delete("TRUE");
260
        } catch (Exception ex) {
261
            throw new RuntimeException("Can't delete all remote changes.", ex);
262
        } finally {
263
           DisposeUtils.disposeQuietly(store);
264
        }
265
    }
266

    
267
    public void delete(OnlineWorkingcopy workspace, String entityCode) {
268
        FeatureStore store = null;
269
        try {
270
            store = workspace.getFeatureStore(TABLE_NAME);
271
            store.delete("\""+COD_ENTITY+"\"='"+entityCode+"'");
272
        } catch (Exception ex) {
273
            throw new RuntimeException("Can't delete remote changes of entity ENTITY["+entityCode+"].", ex);
274
        } finally {
275
           DisposeUtils.disposeQuietly(store);
276
        }
277
    }
278

    
279
    public void delete(FeatureStore store, String entityCode) {
280
        
281
        try {
282
            boolean needFinish = false;
283
            if(store.getMode() == FeatureStore.MODE_QUERY){
284
                store.edit(MODE_PASS_THROUGH);
285
                needFinish = true;
286
            }
287
            store.delete("\""+COD_ENTITY+"\"='"+entityCode+"'");
288
            if(needFinish) {
289
                store.finishEditing();
290
            }
291
        } catch (Exception ex) {
292
            throw new RuntimeException("Can't delete changes.", ex);
293
        }
294

    
295
    }
296

    
297
    public void deleteSelecteds(OnlineWorkingcopy workspace) {
298
        FeatureStore store = null;
299
        try {
300
            store = workspace.getFeatureStore(TABLE_NAME);
301
            store.delete("\""+SELECTED+"\"");
302
        } catch (Exception ex) {
303
            throw new RuntimeException("Can't delete selected remote changes.", ex);
304
        } finally {
305
            DisposeUtils.disposeQuietly(store);
306
        }
307
    }
308
    public DisposableFeatureSetIterable getByEntityCodeAsIterator(OnlineWorkingcopy workspace, String entityCode) {
309
        FeatureStore store = null;
310
        try {
311
            store = workspace.openFeatureStore(TABLE_NAME, true);
312
            FeatureSet changes;
313
            if( StringUtils.isBlank(entityCode) ) {
314
                changes = store.getFeatureSet();
315
            } else {
316
                changes = store.getFeatureSet("\""+COD_ENTITY+"\"='"+entityCode+"'");
317
            }
318
            return changes.iterable();
319
        } catch (Exception ex) {
320
            throw new RuntimeException("Can't retrieve remote changes by entity code (ENTITY["+entityCode+"]).", ex);
321
        } finally {
322
           DisposeUtils.disposeQuietly(store);
323
        }
324
    }
325

    
326

    
327
    public DisposableFeatureSetIterable getSelectedsByEntityCodeAsIterator(OnlineWorkingcopy workspace, String entityCode) {
328
        FeatureStore store = null;
329
        try {
330
            store = workspace.openFeatureStore(TABLE_NAME, true);
331
            FeatureSet changes;
332
            if( StringUtils.isBlank(entityCode) ) {
333
                changes = store.getFeatureSet("\""+SELECTED+"\"");
334
            } else {
335
                changes = store.getFeatureSet("\""+SELECTED+"\" AND \""+COD_ENTITY+"\"='"+entityCode+"'");
336
            }
337
            return changes.iterable();
338
        } catch (Exception ex) {
339
            throw new RuntimeException("Can't retrieve selected remote changes by entity code (ENTITY["+entityCode+"]).", ex);
340
        } finally {
341
           DisposeUtils.disposeQuietly(store);
342
        }
343
    }
344

    
345
    public DisposableFeatureSetIterable getNotSelectedsByEntityCodeAsIterator(OnlineWorkingcopy workspace, String entityCode) {
346
        FeatureStore store = null;
347
        try {
348
            store = workspace.openFeatureStore(TABLE_NAME, true);
349
            FeatureSet changes;
350
            if( StringUtils.isBlank(entityCode) ) {
351
                changes = store.getFeatureSet("NOT \""+SELECTED+"\"");
352
            } else {
353
                changes = store.getFeatureSet("NOT \""+SELECTED+"\" AND \""+COD_ENTITY+"\"='"+entityCode+"'");
354
            }
355
            return changes.iterable();
356
        } catch (Exception ex) {
357
            throw new RuntimeException("Can't retrieve not selected remote changes by entity code (ENTITY["+entityCode+"]).", ex);
358
        } finally {
359
            DisposeUtils.disposeQuietly(store);
360
        }
361
    }
362
    
363
    public GetItemWithSize64<Feature> getByEntityCode(OnlineWorkingcopy workspace, String[] entityCodes) {
364
        FeatureStore store = null;
365
        try {
366
            GetItemWithSize64<Feature>  changes;
367
            store = workspace.openFeatureStore(TABLE_NAME, true);
368
            FeatureQuery query = store.createFeatureQuery();
369
            query.getOrder().add(REVISION_NUMBER, true);
370
            if( ArrayUtils.isNotEmpty(entityCodes)  ) {
371
                ExpressionBuilder builder = store.createExpressionBuilder();
372
                for (String entityCode : entityCodes) {
373
                    if(StringUtils.isNotBlank(entityCode)){
374
                        builder.or( 
375
                                builder.eq(
376
                                        builder.column(COD_ENTITY), 
377
                                        builder.constant(entityCode)
378
                                )
379
                        );
380
                    }
381
                }
382
                String expression = builder.toString();
383
                if(StringUtils.isNotBlank(expression)){
384
                    query.setFilter(expression);
385
                }
386
            }            
387
            query.retrievesAllAttributes();
388
            changes = store.getFeatures64(query,-1);
389
            return changes;
390
        } catch (Exception ex) {
391
            throw new RuntimeException("Can't retrieve remote changes by entity code (ENTITY["+StringUtils.join(entityCodes,",")+"]).", ex);
392
        } finally {
393
           DisposeUtils.disposeQuietly(store);
394
        }
395
    }
396
    
397
    public GetItemWithSize64<Feature> getByEntityCodes(OnlineWorkingcopy workspace, List<String> entityCodes) {
398
        FeatureStore store = null;
399
        try {
400
            store = workspace.openFeatureStore(TABLE_NAME, true);
401
            
402
            GetItemWithSize64<Feature>  changes;
403
            if( entityCodes == null || entityCodes.isEmpty()) {
404
                changes = store.getFeatures64();
405
            } else {
406
                StringBuilder filter = new StringBuilder();
407
                for (String entityCode : entityCodes) {
408
                    if(filter.length()>0){
409
                        filter.append(" OR "); 
410
                    }
411
                    filter.append("\"" + COD_ENTITY + "\"='").append(entityCode).append("'");
412
                }
413
                
414
                changes = store.getFeatures64(filter.toString());
415
            }
416
            return changes;
417
        } catch (Exception ex) {
418
            throw new RuntimeException("Can't retrieve remote changes by entity codes.", ex);
419
        } finally {
420
           DisposeUtils.disposeQuietly(store);
421
        }
422
    }
423
    
424
    public static final FeatureType featureType() {
425
        DataManager dataManager = DALLocator.getDataManager();
426
        EditableFeatureType ft = dataManager.createFeatureType();
427
        ft.setLabel("Online Remote changes");
428
        ft.getTags().set("ID", TABLE_NAME);
429
        ft.add(COD_REMOTECHANGE, DataTypes.STRING)
430
                .setSize(ONLINECODELEN)
431
                .setIsPrimaryKey(true)
432
                .setLabel("Code")
433
                .setReadOnly(false);        
434
        ft.add(COD_ENTITY, DataTypes.STRING)
435
                .setIsIndexed(true)
436
                .setAllowIndexDuplicateds(true)
437
                .setSize(ONLINECODELEN)
438
                .setLabel("Entity code");
439
        ft.add(SELECTED, DataTypes.BOOLEAN)
440
                .setIsIndexed(true)
441
                .setAllowIndexDuplicateds(true)
442
                .setLabel("Selected");
443
        ft.add(FEATUREID, DataTypes.LONG)
444
                .setIsIndexed(false)
445
                .setLabel("Identifier")
446
                .setDescription("Feature code");
447
        ft.add(OPERATION, DataTypes.INTEGER)
448
                .setLabel("Operation")
449
                .setAvailableValues(new DynObjectValueItem[] {
450
                    new DynObjectValueItem(OP_INSERT, "Insert"),
451
                    new DynObjectValueItem(OP_UPDATE, "Update"),
452
                    new DynObjectValueItem(OP_DELETE, "Delete")
453
                });
454
        ft.add(STATUS, DataTypes.INTEGER)
455
                .setLabel("Status")
456
                .setAvailableValues(new DynObjectValueItem[] {
457
                    new DynObjectValueItem(STATE_LOCAL_UNMODIFIED, "Unmodified"),
458
                    new DynObjectValueItem(STATE_LOCAL_MODIFIED, "Modified"),
459
                    new DynObjectValueItem(STATE_CONFLICT, "Conflict")
460
                });
461
        ft.add(REVISION_NUMBER, DataTypes.LONG)
462
                .setIsIndexed(true)
463
                .setAllowIndexDuplicateds(true)
464
                .setLabel("Revision number");
465

    
466
        ft.add(FEATURE_DATA, DataTypes.STRING)
467
                .setSize(RECOMENDED_SIZE_FOR_CLOB)
468
                .setLabel("Data");
469
        
470
        return ft.getNotEditableCopy();
471
    }
472
    
473
    public DisposableFeatureSetIterable getGroupedByEntity(OnlineWorkingcopy workspace) {
474
        FeatureStore store = null;
475
        try {
476
            store = workspace.openFeatureStore(TABLE_NAME, true);
477
            FeatureQuery query = store.createFeatureQuery();
478

    
479
            query.getOrder().add(COD_ENTITY,true);
480
            query.getGroupByColumns().add(COD_ENTITY);
481
            query.retrievesAllAttributes();
482
            DisposableFeatureSetIterable changes = store.getFeatureSet(query).iterable();
483
            return changes;
484
        } catch (Exception ex) {
485
            throw new RuntimeException("Can't retrieve changes grouped by entity.", ex);
486
        } finally {
487
            DisposeUtils.disposeQuietly(store);
488
        }
489
    }
490
    
491
    public boolean updateNeedMerge(OnlineWorkingcopy workspace, String entityCode) {
492
        FeatureStore store = null;
493
        try {
494
            store = workspace.getFeatureStore(TABLE_NAME);
495
            FeatureQuery query = store.createFeatureQuery("NOT \""+SELECTED+"\" AND \""+COD_ENTITY+"\"='"+entityCode+"'");
496
            query.setLimit(1);
497
            Feature f = store.findFirst(query);
498
            return f != null;
499
        } catch (Exception ex) {
500
            throw new RuntimeException("Can't retrieve if need merge for entity code (ENTITY["+entityCode+"]).", ex);
501
        } finally {
502
           DisposeUtils.disposeQuietly(store);
503
        }
504
    }
505
    
506
    
507
    public boolean updateStateFromLocalChanges(OnlineWorkingcopy workspace, int status) {
508
        
509
        String sql = String.format(OnlineUtils.getSqlTemplate(workspace.getExplorer().getProviderName(), "updateStateFromLocalChanges"), status);
510
        workspace.getExplorer().execute(sql);
511
                
512
        return true;
513
    }
514
    
515
    public long getCountRemoteChangesOfEntity(OnlineWorkingcopy workspace, DataTransaction transaction, String entityCode) {
516
        FeatureStore store = null;
517
        FeatureSet changes = null;
518
        try {
519
            if( transaction==null ) {
520
                store = workspace.getFeatureStore(TABLE_NAME);
521
            } else {
522
                store = transaction.getFeatureStore(TABLE_NAME);
523
                if( store == null ) {
524
                    store = workspace.getFeatureStore(TABLE_NAME);
525
                } else {
526
                    DisposeUtils.bind(store);
527
                }
528
            }
529
            if( StringUtils.isBlank(entityCode) ) {
530
                throw new IllegalArgumentException("entityCode is required.");
531
            }
532
            changes = store.getFeatureSet(
533
                    "\""+COD_ENTITY+"\"='"+entityCode+"'"
534
            );
535
            return changes.size64();
536
        } catch (Exception ex) {
537
            throw new RuntimeException("Can't retrieve changes by entity.", ex);
538
        } finally {
539
            DisposeUtils.disposeQuietly(changes);
540
            DisposeUtils.disposeQuietly(store);
541
        }
542
    }
543
    
544
}