Revision 9512 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/OnlineWorkspaceImpl.java

View differences:

OnlineWorkspaceImpl.java
19 19
import java.util.List;
20 20
import java.util.Map;
21 21
import java.util.Set;
22
import java.util.logging.Level;
22 23
import javax.json.JsonArray;
23 24
import javax.json.JsonObject;
24 25
import javax.json.JsonValue;
......
34 35
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
35 36
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
36 37
import org.gvsig.expressionevaluator.ExpressionUtils;
38
import org.gvsig.expressionevaluator.GeometryExpressionBuilder;
37 39
import org.gvsig.fmap.dal.DALLocator;
38 40
import org.gvsig.fmap.dal.DataManager;
39 41
import org.gvsig.fmap.dal.DataServerExplorer;
......
53 55
import org.gvsig.fmap.dal.feature.EditableFeatureType;
54 56
import org.gvsig.fmap.dal.feature.Feature;
55 57
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
58
import org.gvsig.fmap.dal.feature.FeatureQuery;
56 59
import org.gvsig.fmap.dal.feature.FeatureReference;
57 60
import org.gvsig.fmap.dal.feature.FeatureSet;
58 61
import org.gvsig.fmap.dal.feature.FeatureStore;
......
66 69
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
67 70
import org.gvsig.fmap.dal.store.jdbc2.JDBCServerExplorer;
68 71
import org.gvsig.fmap.geom.Geometry;
72
import org.gvsig.fmap.geom.GeometryException;
69 73
import org.gvsig.fmap.geom.GeometryLocator;
70 74
import org.gvsig.fmap.geom.GeometryManager;
71 75
import org.gvsig.fmap.geom.primitive.Envelope;
72 76
import org.gvsig.json.Json;
77
import org.gvsig.json.JsonObjectBuilder;
73 78
import org.gvsig.online.lib.api.OnlineCodeGenerator;
74 79
import org.gvsig.online.lib.api.OnlineDownloader;
75 80
import org.gvsig.online.lib.api.OnlineLayer;
......
122 127
import org.gvsig.online.lib.api.workingcopy.OnlineRemoteChange;
123 128
import org.gvsig.online.lib.api.workingcopy.OnlineWorkingcopy;
124 129
import org.gvsig.online.lib.api.workingcopy.OnlineWorkingcopyChange;
125
import org.gvsig.online.lib.api.workingcopy.OnlineWorkingcopyChanges;
130
import org.gvsig.online.lib.api.workingcopy.WorkingArea;
126 131
import static org.gvsig.online.lib.impl.OnlineManagerImpl.INTERNAL_WORKSPACE_TABLES;
127 132
import org.gvsig.online.lib.impl.OnlineProjectImpl;
128 133
import org.gvsig.online.lib.impl.OnlineSiteImpl;
129 134
import org.gvsig.online.lib.impl.OnlineUtils;
130
import org.gvsig.online.lib.impl.PatchGenerator;
131 135
import org.gvsig.online.lib.impl.TilesCalculator;
132 136
import org.gvsig.online.lib.impl.workspace.tables.EntitiesTable;
133 137
import org.gvsig.online.lib.impl.workspace.tables.EntitiesTable.EntityRow;
......
149 153
import org.gvsig.tools.observer.Notification;
150 154
import org.gvsig.tools.observer.Observable;
151 155
import org.gvsig.tools.observer.Observer;
156
import org.gvsig.tools.patch.PatchGenerator;
152 157
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
153 158
import org.gvsig.tools.swing.api.ChangeListenerHelper;
154 159
import org.gvsig.tools.swing.api.ToolsSwingLocator;
......
160 165
import org.gvsig.tools.util.Rewind;
161 166
import org.slf4j.Logger;
162 167
import org.slf4j.LoggerFactory;
168
import org.gvsig.online.lib.api.workingcopy.OnlineChanges;
163 169

  
164 170
/**
165 171
 *
......
179 185
//    public static final String CONFIG_REPOSITORY_ENTITY_CACHE_TIME_NAME = "REPOSITORY_ENTITY_CACHE_TIME";
180 186
    public static final String CONFIG_OFFLINE = "OFFLINE";
181 187
    public static final String CONFIG_ENTITY_LABEL_TEMPLATE = "ENTITY_LABEL_TEMPLATE";
188
    public static final String CONFIG_CURRENT_WORKINGAREA = "CURRENT_WORKINGAREA";
182 189
//    public static final String CONFIG_USE_SAFE_MODE = "USE_SAFE_MODE";
183 190

  
184 191
    private final Map<String, FeatureStore> storesCache;
......
202 209
    private String entityLabelTemplate;
203 210
    private boolean disposed = false;
204 211
    private Observer changeUserObserver;
212
    private WorkingArea currentWorkingArea;
205 213

  
206 214
    public OnlineWorkspaceImpl(JDBCServerExplorer wsexplorer, OnlineCodeGenerator codeGenerator, OnlineProject project, String label) {
207 215
        // Usado en la inicializacion del workspace
......
250 258
                CONFIG_WORKSPACE_LABEL_NAME,
251 259
                CONFIG_OFFLINE,
252 260
//                CONFIG_USE_SAFE_MODE,
253
                CONFIG_ENTITY_LABEL_TEMPLATE
261
                CONFIG_ENTITY_LABEL_TEMPLATE,
262
                CONFIG_CURRENT_WORKINGAREA
254 263
        );
255 264
        this.code = vars.get(CONFIG_WORKSPACE_CODE_NAME);
256 265
        if (this.code == null) {
......
268 277
        if (this.project == null) {
269 278
            throw new RuntimeException("Can't retrieve repository from workspace '" + this.getMessageLabel() + "'");
270 279
        }
280
        this.currentWorkingArea = (WorkingAreaImpl) Json.toObject(vars.get(CONFIG_CURRENT_WORKINGAREA));
271 281
        this.setCurrentUserCode(this.project, vars.get(CONFIG_USER_NAME));
272 282
        this.setAuthenticationToken(this.project, vars.get(CONFIG_AUTHENTICATIONTOKEN_NAME));
273 283
        this.label = vars.get(CONFIG_WORKSPACE_LABEL_NAME);
274 284
        this.changeUserObserver = createChangeUserObserver();
275 285
        
286
//        this.refreshCodeGeneratorSequence();
287
        
276 288
//        LOGGER.debug("===: CREATE WORKSPACE "+ hexId(this)+ " (open code='"+this.code+"', label='"+this.label+"')");
277 289
    }
278 290

  
......
308 320
        return this.codeGenerator.generateCodeString();
309 321
    }
310 322

  
311
    public final long createUniqueCodeLong() {
312
        return this.codeGenerator.generateCodelong();
323
    public final long createUniqueCodeLong(String entityName) {
324
        if(!this.codeGenerator.isInitialized(entityName)){
325
            this.refreshCodeGeneratorSequence(entityName);
326
        }
327
        return this.codeGenerator.generateCodelong(entityName);
328
        
313 329
    }
314 330

  
315 331
    @Override
......
913 929
                    entity.setCRS(crs);
914 930
                }
915 931
            }
916
            entity.setState(STATE_LOCAL_NEW);
932
            entity.setState(STATE_LOCAL_UNMODIFIED);
917 933
            entity.insert();
918 934
            addWorkspaceEntity(entity);
919 935

  
......
1180 1196
            }
1181 1197
        }
1182 1198
        try {
1199
            Feature previousChange = null;
1183 1200
            long featureCode = feature.getLong(entity.getFeatureIdFieldName());
1184 1201
            Integer previousOperation = null;
1185 1202
            if (previousOperations != null) {
1186 1203
                previousOperation = previousOperations.get(featureCode);
1187 1204
            } else {
1188
                Feature previousChange = changesStore.findFirst(WorkspaceChangesTable.FEATUREID + " = '" + featureCode + "'"); // and " + WorkspaceChangesTable.OPERATION+ " = " + operation);
1205
                previousChange = changesStore.findFirst(WorkspaceChangesTable.FEATUREID + " = '" + featureCode + "'"); // and " + WorkspaceChangesTable.OPERATION+ " = " + operation);
1189 1206
                if (previousChange != null) {
1190 1207
                    previousOperation = previousChange.getInt(WorkspaceChangesTable.OPERATION);
1191 1208
                }
......
1211 1228
                        switch (previousOperation) {
1212 1229
                            case OP_INSERT:
1213 1230
                            case OP_UPDATE:
1231
                                //TODO: Migrar a VCSGIS
1232
                                if(previousChange != null ) {
1233
                                    WorkspaceChangeRow change = new WorkspaceChangeRow(this, previousChange);
1234
                                    if(change.getStatus() == STATE_CONFLICT){
1235
                                        change.setStatus(STATE_LOCAL_MODIFIED);
1236
                                        change.update(changesStore);
1237
                                    }
1238
                                }
1214 1239
                                return ERR_OK;
1215 1240
                            case OP_DELETE:
1216 1241
                                LOGGER.warn("A update change cannot be added as there is a previous change with operation delete (featureCode=" + featureCode + ")");
......
1533 1558
    }
1534 1559

  
1535 1560
    @Override
1536
    public OnlineWorkingcopyChanges<OnlineWorkingcopyChange> getLocalChanges() {
1561
    public OnlineChanges<OnlineWorkingcopyChange> getLocalChanges() {
1537 1562
        return getLocalChanges(null);
1538 1563
    }
1539 1564

  
1540 1565
    @Override
1541
    public OnlineWorkingcopyChanges<OnlineWorkingcopyChange> getLocalChanges(List<OnlineEntity> entities) {
1566
    public OnlineChanges<OnlineWorkingcopyChange> getLocalChanges(List<OnlineEntity> entities) {
1542 1567
        WorkspaceChangesTable changesTable = new WorkspaceChangesTable();
1543 1568
        ChangesImpl changes = new ChangesImpl<WorkspaceChangeRow>(changesTable.getByEntityCode(this, entities), WorkspaceChangesTable.SELECTED) {
1544 1569
            @Override
......
2085 2110
    }
2086 2111

  
2087 2112
    @Override
2088
    public OnlineWorkingcopyChanges<OnlineRemoteChange> getRemoteChanges() {
2113
    public OnlineChanges<OnlineRemoteChange> getRemoteChanges() {
2089 2114
        return getRemoteChangesByEntity((String) null);
2090 2115
    }
2091 2116

  
2092 2117
    @Override
2093
    public OnlineWorkingcopyChanges<OnlineRemoteChange> getRemoteChangesByEntity(String... entityNames) {
2118
    public OnlineChanges<OnlineRemoteChange> getRemoteChangesByEntity(String... entityNames) {
2094 2119
        String[] entityCodes = null;
2095 2120
        if (ArrayUtils.isNotEmpty(entityNames)) {
2096 2121
            entityCodes = new String[entityNames.length];
......
2408 2433
            this.addStoreIgnoreChanges(store);
2409 2434
            store.edit(FeatureStore.MODE_APPEND, FeatureStore.SUBMODE_MERGE);
2410 2435
            GeometryManager geomManager = GeometryLocator.getGeometryManager();
2436
            IProjection layerProjection = layer.getProjection();
2437
            String geometryName = store.getDefaultFeatureTypeQuietly().getDefaultGeometryAttributeName();
2411 2438
            int nenv = 0;
2412 2439
            for (Envelope env : envs) {
2413 2440
                nenv++;
......
2417 2444
                        status.cancel();
2418 2445
                        throw new UserCancelTaskException();
2419 2446
                    }
2420
                    JsonObject feature_json = it.next();
2421
                    EditableFeature feature = null;
2422
                    Geometry geom = null;
2423
                    JsonObject properties = feature_json.getJsonObject("properties");
2424
                    JsonObject geom_json = feature_json.getJsonObject("geometry");
2425
                    if( geom_json!=null ) {
2426
                        geom = geomManager.createFrom(geom_json);
2427
                        if( geom.getProjection()==null ) {
2428
                            geom.setProjection(layer.getProjection());
2429
                        }
2447
                    JsonObject feature_online_json = it.next();
2448
                    JsonObject feature_desktop_json = convertOnlineToDesktopFeature(feature_online_json, geometryName, geomManager, layerProjection);
2449
                    if(feature_desktop_json == null){
2450
                        continue;
2430 2451
                    }
2431
                    if( properties==null ) {
2432
                        if( geom == null ) {
2433
                            continue;
2434
                        }
2435
                        feature = store.createNewFeature();                        
2436
                    } else {
2437
                        feature = store.createNewFeature(properties);
2438
                    }
2439
                    feature.setDefaultGeometry(geom);
2440
                    store.insert(feature); // Insert or replace
2452
                    EditableFeature feature = store.createNewFeature(feature_desktop_json);
2453
                    store.insert(feature);
2454
//                    
2455
//                    EditableFeature feature = null;
2456
//                    Geometry geom = null;
2457
//                    JsonObject properties = feature_json.getJsonObject("properties");
2458
//                    JsonObject geom_json = feature_json.getJsonObject("geometry");
2459
//                    if( geom_json!=null ) {
2460
//                        geom = geomManager.createFrom(geom_json);
2461
//                        if( geom.getProjection()==null ) {
2462
//                            geom.setProjection(layer.getProjection());
2463
//                        }
2464
//                    }
2465
//                    if( properties==null ) {
2466
//                        if( geom == null ) {
2467
//                            continue;
2468
//                        }
2469
//                        feature = store.createNewFeature();                        
2470
//                    } else {
2471
//                        feature = store.createNewFeature(properties);
2472
//                    }
2473
//                    feature.setDefaultGeometry(geom);
2474
//                    store.insert(feature); // Insert or replace
2441 2475
                }
2442 2476
            }
2443 2477
            status.setIndeterminate();
......
2458 2492
        }
2459 2493
        return 0;
2460 2494
    }
2495
    
2496
    private JsonObject convertOnlineToDesktopFeature(JsonObject online_json, String geometryName, GeometryManager geomManager, IProjection proj) {
2497
        Geometry geom = null;
2498
        JsonObject properties = online_json.getJsonObject("properties");
2499
        JsonObject geom_json = online_json.getJsonObject("geometry");
2500
        if (geom_json != null) {
2501
            try {
2502
                geom = geomManager.createFrom(geom_json);
2503
            } catch (Exception ex) {
2504
            }
2505
            if (geom != null && geom.getProjection() == null) {
2506
                geom.setProjection(proj);
2507
            }
2508
        }
2509
        if (properties == null) {
2510
            if (geom == null) {
2511
                return null;
2512
            }
2513
            JsonObjectBuilder builder = Json.createObjectBuilder();
2514
            builder.add(geometryName, geom.convertToHexWKBQuietly());
2515
            return builder.build();
2516
        }
2517
        JsonObjectBuilder builder = Json.createObjectBuilder();
2518
        if (geom == null) {
2519
            builder.addNull(geometryName);
2520
        } else {
2521
            builder.add(geometryName, geom.convertToHexWKBQuietly());
2522
        }
2523
        builder.addAll(properties);
2524
        return builder.build();
2525
    }
2461 2526

  
2462 2527
    public String getCurrentUserCode() {
2463 2528
        return getCurrentUserCode(null);
......
2658 2723
    }
2659 2724

  
2660 2725
    @Override
2661
    public int updateClean(String entityCode) {
2662
        return updateClean(entityCode, null);
2726
    public int removeRemoteChanges(String entityCode) {
2727
        return removeRemoteChanges(entityCode, null);
2663 2728
    }
2664 2729

  
2665 2730
    @Override
2666
    public int updateClean(String entityCode, SimpleTaskStatus status) {
2731
    public int removeRemoteChanges(String entityCode, SimpleTaskStatus status) {
2667 2732
        OnlineEntity entity = this.getEntity(entityCode);
2668 2733
        if (entity == null) {
2669 2734
            return ERR_ENTITY_NOT_EXISTS;
......
2677 2742
        } else {
2678 2743
            status.push();
2679 2744
        }
2745
        FeatureStore remoteChangesStore = null;
2746
        FeatureStore localChangesStore = null;
2747
        FeatureStore entitiesStore = null;
2680 2748
        try {
2681 2749
            status.message("Deleting temporary remote changes (" + entity.getEntityName() + ")");
2682
            RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2683
            remoteChangesTable.delete(this, entityCode);
2750
            remoteChangesStore = openFeatureStore(RemoteChangesTable.TABLE_NAME, false);
2751
            localChangesStore = openFeatureStore(WorkspaceChangesTable.TABLE_NAME, false);
2752
            entitiesStore = openFeatureStore(EntitiesTable.TABLE_NAME, false);
2753
            removeRemoteChanges(remoteChangesStore, localChangesStore, entitiesStore, (EntityRow)entity);
2684 2754
            status.message("Delete temporary remote changes completed");
2685 2755
            status.terminate();
2686 2756
            return ERR_OK;
......
2691 2761
            return ERR_CANT_UPDATE_CLEAN;
2692 2762
        } finally {
2693 2763
            status.pop();
2764
            DisposeUtils.dispose(remoteChangesStore);
2765
            DisposeUtils.dispose(localChangesStore);
2766
            DisposeUtils.dispose(entitiesStore);
2694 2767
        }
2695 2768

  
2696 2769
    }
2770
    
2771
    private void removeRemoteChanges(FeatureStore remoteChangesStore, FeatureStore localChangesStore, FeatureStore entitiesStore, EntityRow entity) throws DataException {
2772
        RemoteChangesTable remoteChangesTable = new RemoteChangesTable();
2773
        remoteChangesTable.delete(remoteChangesStore, entity.getEntityCode());
2774
        WorkspaceChangesTable localChangesTable = new WorkspaceChangesTable();
2775
        localChangesTable.changeState(localChangesStore, entity.getEntityCode(), STATE_CONFLICT, STATE_LOCAL_UNMODIFIED);
2776
        if(entity.getState() == STATE_CONFLICT){
2777
            entity.setState(STATE_LOCAL_MODIFIED);
2778
            boolean needFinish = false;
2779
            if(entitiesStore.getMode() == FeatureStore.MODE_QUERY){
2780
                entitiesStore.edit(MODE_PASS_THROUGH);
2781
                needFinish = true;
2782
            }
2783
            entity.update(entitiesStore);
2784
            if(needFinish){
2785
                entitiesStore.finishEditing();
2786
            }
2787
        }
2788
    }
2697 2789

  
2698 2790
    @Override
2699 2791
    public boolean canUpdate(MutableObject<String> message, String tableName) {
......
2964 3056
                            throw new UserCancelTaskException();
2965 3057
                        }
2966 3058
                        RemoteChangeRow remoteChangeRow = new RemoteChangeRow(this, feature);
2967
                        Feature f = userStore.findFirst("\"" + lentity.getFeatureIdFieldName() + "\" = '" + remoteChangeRow.getRelatedFeatureCode() + "'");
3059
                        Feature f = userStore.findFirst("\"" + lentity.getFeatureIdFieldName() + "\" = " + remoteChangeRow.getRelatedFeatureCode());
2968 3060
                        switch (remoteChangeRow.getOperation()) {
2969 3061
                            case OP_INSERT:
2970 3062
                                LOGGER.debug("===: UPDATE: insert");
......
2992 3084
                            case OP_DELETE:
2993 3085
                                LOGGER.debug("===: UPDATE: delete");
2994 3086
                                if (f != null) {
2995
                                    userStore.delete("\"" + dataCodeFieldName + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
2996

  
3087
                                    userStore.delete("\"" + dataCodeFieldName + "\"=" + remoteChangeRow.getRelatedFeatureCode());
2997 3088
                                    ef = userStore.createNewFeature(f);
2998
                                    String newRelatedFeatureCode = this.createUniqueCode();
2999
                                    ef.setString(lentity.getFeatureIdFieldName(), newRelatedFeatureCode);
3089
                                    String localEntityName = lentity.getEntityName();
3090
                                    long newRelatedFeatureCode = this.createUniqueCodeLong(localEntityName);
3091
                                    ef.setLong(lentity.getFeatureIdFieldName(), newRelatedFeatureCode);
3000 3092
                                    userStore.insert(ef);
3001 3093

  
3002
                                    workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\"='" + remoteChangeRow.getRelatedFeatureCode() + "'");
3003
                                    LOGGER.debug("===: UPDATE: add insert operation to RelatedFeatureCode "+newRelatedFeatureCode);
3094
                                    workspaceChangesStore.delete("\"" + WorkspaceChangesTable.FEATUREID + "\"=" + remoteChangeRow.getRelatedFeatureCode());
3095
                                    LOGGER.debug("===: UPDATE: add insert operation to RelatedFeatureCode " + newRelatedFeatureCode);
3004 3096
                                    this.addChange(null, lentity, OP_INSERT, workspaceChangesStore, ef, null, null);
3005 3097
                                    localChangesModifieds.increment();
3006 3098
                                } else {
......
3128 3220
    }
3129 3221

  
3130 3222
    @Override
3131
    public int synchronize(OnlineEntity entity, SimpleTaskStatus status) {
3223
    public int synchronize(OnlineEntity entity, Envelope workingArea, SimpleTaskStatus status) {
3132 3224
        I18nManager i18n = ToolsLocator.getI18nManager();
3133 3225
        if (status == null) {
3134 3226
            status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus(i18n.getTranslation("_Synchronizing"));
......
3143 3235
        
3144 3236
        WorkspaceChangesTable wct = new WorkspaceChangesTable();
3145 3237
        Iterator<Geometry> geoms = null;
3238
        Iterator<Geometry> geoms2 = null;
3146 3239
        FeatureStore remoteStore = null;
3147 3240
        FeatureStore localStore = null;
3148 3241
        FeatureSet remoteSet = null;
3149
        DisposableIterator remoteIt = null;
3242
        DisposableIterator<Feature> remoteIt = null;
3150 3243
        FeatureSet localSet = null;
3151
        DisposableIterator localIt = null;
3244
        DisposableIterator<Feature> localIt = null;
3245

  
3246
        FeatureStore localChangesStore = null;
3247
        FeatureStore remoteChangesStore = null;
3248
        FeatureStore entitiesStore = null;
3249
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
3152 3250
        
3153 3251
        try {
3252
            OnlineWorkspaceImpl wc = this;
3154 3253
            DisposableFeatureSetIterable it = wct.getSelectedsByEntityCodeAsIterator(this, entity.getEntityCode());
3155

  
3156 3254
            geoms = new Iterator<Geometry>() {
3157 3255
                @Override
3158 3256
                public boolean hasNext() {
......
3161 3259

  
3162 3260
                @Override
3163 3261
                public Geometry next() {
3164
                    return it.next().getDefaultGeometry();
3262
                    Feature f = it.next();
3263
                    WorkspaceChangeRow row = new WorkspaceChangeRow(wc, f);
3264
                    if (row.getOperation() == OP_DELETE) {
3265
                        return null;
3266
                    }
3267
                    return row.getRelatedFeature().getDefaultGeometry();
3165 3268
                }
3166 3269
            };
3167 3270

  
3271
            DisposableFeatureSetIterable it2 = wct.getSelectedsByEntityCodeAsIterator(this, entity.getEntityCode());
3272
            geoms2 = new Iterator<Geometry>() {
3273
                @Override
3274
                public boolean hasNext() {
3275
                    return it2.hasNext();
3276
                }
3277

  
3278
                @Override
3279
                public Geometry next() {
3280
                    try {
3281
                        Feature f = it2.next();
3282
                        WorkspaceChangeRow row = new WorkspaceChangeRow(wc, f);
3283
                        
3284
                        JsonObject dataAsJson = row.getDataAsJson();
3285
                        if(dataAsJson == null){
3286
                            return null;
3287
                        }
3288
                        String geom_wkb = dataAsJson.getString(entity.getGeometryFieldName());
3289
                        if(geom_wkb == null) {
3290
                            return null;
3291
                        }
3292
                        return geomManager.createFrom(geom_wkb);
3293
                    } catch (GeometryException ex) {
3294
                        LOGGER.warn("Can't get geometry of workspace change", ex);
3295
                        return null;
3296
                    }
3297
                }
3298
            };
3299

  
3168 3300
            TilesCalculator tilesCalculator = new TilesCalculator();
3169
            List<Envelope> envs = tilesCalculator.calculateEnvelopes(entity.getTileSize(), geoms);
3301
            List<Envelope> envs = tilesCalculator.calculateEnvelopes(
3302
                entity.getTileSize(), 
3303
                new ChainedIterator<>(
3304
                    geoms, 
3305
                    geoms2, 
3306
                    workingArea == null?Collections.EMPTY_LIST.iterator():Collections.singletonList(workingArea.getGeometry()).iterator()
3307
                )
3308
            );
3170 3309

  
3171 3310
            OnlineLayer layer = this.project.getLayer(
3172 3311
                (OnlineLayer t) -> StringUtils.equals(t.getName(), entity.getEntityName()),
3173 3312
                SimpleTaskStatus.FAKE_STATUS
3174 3313
            );
3175 3314
            File f = ((HasAFile) this.getExplorerParameters()).getFile();
3176
            File temp = ToolsLocator.getFoldersManager().getUniqueTemporaryFile(H2SpatialUtils.removeH2FileNameExtension(f.getAbsolutePath()));
3315
            File tmpRemote = ToolsLocator.getFoldersManager().getUniqueFile(H2SpatialUtils.removeH2FileNameExtension(f.getAbsolutePath())+"_tmp_"+entity.getEntityName());
3177 3316
            DataManager dataManager = DALLocator.getDataManager();
3178 3317
            DataServerExplorerParameters expParameters = DALLocator.getDataManager().createServerExplorerParameters(FeatureStore.H2SPATIAL_PROVIDER_NAME);
3179
            ((HasAFile) expParameters).setFile(temp);
3318
            ((HasAFile) expParameters).setFile(tmpRemote);
3180 3319
            DataServerExplorer explorer = dataManager.openServerExplorer(FeatureStore.H2SPATIAL_PROVIDER_NAME, expParameters);
3181 3320
            JDBCNewStoreParameters params = (JDBCNewStoreParameters) explorer.getAddParameters(entity.getEntityName());
3182 3321
            EditableFeatureType ft = params.getDefaultFeatureType();
......
3188 3327
            remoteStore = (FeatureStore) dataManager.openStore(FeatureStore.H2SPATIAL_PROVIDER_NAME, storeParams);
3189 3328
            remoteStore.edit(FeatureStore.MODE_APPEND, FeatureStore.SUBMODE_MERGE);
3190 3329

  
3330
            String geometryName = entity.getFeatureType().getDefaultGeometryAttributeName();
3331
            IProjection layerProj = entity.getCRSAsProjection();
3191 3332
            for (Envelope env : envs) {
3192 3333
                Iterator<JsonObject> data = layer.getData(env, 1000, status);
3193 3334
                while (data.hasNext()) {
......
3195 3336
                        throw new UserCancelTaskException();
3196 3337
                    }
3197 3338
                    JsonObject json = data.next();
3339
                    JsonObject properties_json = json.getJsonObject("properties");
3198 3340
                    EditableFeature feat = remoteStore.createNewFeature();
3199
                    feat.set(FEATURECODE_FIELD_NAME, json.getInt(FEATURECODE_FIELD_NAME, 0));
3200
                    feat.set(FEATUREVERSION_FIELD_NAME, json.getInt(FEATUREVERSION_FIELD_NAME, 0));
3201
                    feat.set("feature", json.toString());
3341
                    feat.set(FEATURECODE_FIELD_NAME, properties_json.getInt(FEATURECODE_FIELD_NAME, 0));
3342
                    feat.set(FEATUREVERSION_FIELD_NAME, properties_json.getInt(FEATUREVERSION_FIELD_NAME, 0));
3343
                    feat.set("feature", convertOnlineToDesktopFeature(json, geometryName, geomManager, layerProj).toString());
3202 3344
                    remoteStore.insert(feat);
3203 3345
                }
3204 3346
            }
3205 3347
            remoteStore.finishEditing();
3206
            FeatureStore localChangesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME, true);
3207
            FeatureStore remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME, true);
3348

  
3349
            localChangesStore = this.openFeatureStore(WorkspaceChangesTable.TABLE_NAME, true);
3350
            remoteChangesStore = this.openFeatureStore(RemoteChangesTable.TABLE_NAME, true);
3351
            entitiesStore = this.openFeatureStore(EntitiesTable.TABLE_NAME, true);
3352
            final FeatureStore finalLocalChangesStore = localChangesStore;
3353
            final FeatureStore finalRemoteChangesStore = remoteChangesStore;
3354

  
3355
            removeRemoteChanges(remoteChangesStore, localChangesStore, entitiesStore, (EntityRow)entity);
3356
            
3208 3357
            remoteChangesStore.edit(FeatureStore.MODE_APPEND);
3209
            OnlineWorkspaceImpl wc = this;
3358
            localChangesStore.edit(FeatureStore.MODE_PASS_THROUGH);
3359
            
3210 3360
            PatchGenerator.PatchHandler<Feature> handler = new PatchGenerator.PatchHandler<Feature>() {
3361
                WorkspaceChangeRow lastLocalChange = null;
3362
                
3211 3363
                @Override
3212 3364
                public int compareId(Feature r, Feature l) {
3213 3365
                    return Integer.compare(r.getInt(FEATURECODE_FIELD_NAME), l.getInt(FEATURECODE_FIELD_NAME));
......
3220 3372

  
3221 3373
                @Override
3222 3374
                public boolean isLocalChange(Feature l) {
3223
                    WorkspaceChangeRow row = wct.find(wc, localChangesStore, entity.getEntityCode(), l.getInt(FEATURECODE_FIELD_NAME));
3224
                    return row != null;
3375
                    lastLocalChange = wct.find(wc, finalLocalChangesStore, entity.getEntityCode(), l.getInt(FEATURECODE_FIELD_NAME));
3376
                    return lastLocalChange != null;
3225 3377
                }
3226 3378

  
3227 3379
                @Override
......
3230 3382
                }
3231 3383

  
3232 3384
                @Override
3233
                public void addRemoteChangeDelete(Feature r) {
3385
                public void addRemoteChangeDelete(Feature l, boolean conflict) {
3234 3386
                    RemoteChangeRow row = new RemoteChangeRow(wc);
3235
                    row.setData(r.getString("feature"));
3387
                    row.setData(l.toJson().toString());
3236 3388
                    row.setEntityCode(entity.getEntityCode());
3237 3389
                    row.setOperation(OP_DELETE);
3238
                    row.setRevisionNumber(r.getInt(FEATUREVERSION_FIELD_NAME));
3390
                    row.setRevisionNumber(l.getInt(FEATUREVERSION_FIELD_NAME));
3239 3391
                    row.setSelected(true);
3240
                    row.setStatus(STATE_LOCAL_UNMODIFIED);
3241
                    row.insert(remoteChangesStore);
3392
                    row.setStatus(conflict ? STATE_CONFLICT : STATE_LOCAL_UNMODIFIED);
3393
                    row.setRelatedFeatureCode(l.getInt(FEATURECODE_FIELD_NAME));
3394
                    row.setCode(createUniqueCode());
3395
                    row.insert(finalRemoteChangesStore);
3396
                    if (conflict) {
3397
                        if (lastLocalChange == null
3398
                            || !(lastLocalChange.getEntityCode().equals(row.getEntityCode())
3399
                            && lastLocalChange.getRelatedFeatureCode() == row.getRelatedFeatureCode())) {
3400

  
3401
                            lastLocalChange = wct.find(wc, finalLocalChangesStore, entity.getEntityCode(), l.getInt(FEATURECODE_FIELD_NAME));
3402
                        }
3403
                        if(lastLocalChange != null && lastLocalChange.getStatus() != STATE_CONFLICT) {
3404
                            lastLocalChange.setStatus(STATE_CONFLICT);
3405
                            lastLocalChange.update(finalLocalChangesStore);
3406
                        }
3407
                        ((EntityRow)entity).setState(STATE_CONFLICT);
3408
                    }
3242 3409
                }
3243 3410

  
3244 3411
                @Override
......
3250 3417
                    row.setRevisionNumber(r.getInt(FEATUREVERSION_FIELD_NAME));
3251 3418
                    row.setSelected(true);
3252 3419
                    row.setStatus(conflict ? STATE_CONFLICT : STATE_LOCAL_UNMODIFIED);
3253
                    row.insert(remoteChangesStore);
3420
                    row.setRelatedFeatureCode(r.getInt(FEATURECODE_FIELD_NAME));
3421
                    row.setCode(createUniqueCode());
3422
                    row.insert(finalRemoteChangesStore);
3423
                    if (conflict) {
3424
                        if (lastLocalChange == null
3425
                            || !(lastLocalChange.getEntityCode().equals(row.getEntityCode())
3426
                            && lastLocalChange.getRelatedFeatureCode() == r.getInt(FEATURECODE_FIELD_NAME))) {
3427

  
3428
                            lastLocalChange = wct.find(wc, finalLocalChangesStore, entity.getEntityCode(), r.getInt(FEATURECODE_FIELD_NAME));
3429
                        }
3430
                        if(lastLocalChange != null && lastLocalChange.getStatus() != STATE_CONFLICT) {
3431
                            lastLocalChange.setStatus(STATE_CONFLICT);
3432
                            lastLocalChange.update(finalLocalChangesStore);
3433
                        }
3434
                        ((EntityRow)entity).setState(STATE_CONFLICT);
3435
                    }
3254 3436
                }
3255 3437

  
3256 3438
                @Override
......
3262 3444
                    row.setRevisionNumber(r.getInt(FEATUREVERSION_FIELD_NAME));
3263 3445
                    row.setSelected(true);
3264 3446
                    row.setStatus(STATE_LOCAL_UNMODIFIED);
3265
                    row.insert(remoteChangesStore);
3447
                    row.setCode(createUniqueCode());
3448
                    row.insert(finalRemoteChangesStore);
3266 3449
                }
3267 3450
            };
3268 3451

  
3269
            PatchGenerator<Object> patchGenerator = new PatchGenerator<>(handler);
3452
            PatchGenerator<Feature> patchGenerator = PatchGenerator.create(handler);
3270 3453

  
3271 3454
            localStore = this.openFeatureStore(entity);
3272 3455
            remoteSet = remoteStore.getFeatureSet((String) null, FEATURECODE_FIELD_NAME);
3273 3456
            remoteIt = remoteSet.fastIterator();
3274
            localSet = localStore.getFeatureSet((String) null, FEATURECODE_FIELD_NAME);
3457
            GeometryExpressionBuilder expBuilder = (GeometryExpressionBuilder) localStore.createExpressionBuilder();
3458
            FeatureType localStoreFt = localStore.getDefaultFeatureTypeQuietly();
3459
            String geomName = localStoreFt.getDefaultGeometryAttributeName();
3460
            IProjection localStoreProj = localStoreFt.getDefaultSRS();
3461
            for (Envelope env : envs) {
3462
                expBuilder.or(
3463
                    expBuilder.ST_Intersects(
3464
                        expBuilder.column(geomName),
3465
                        expBuilder.envelope(env, localStoreProj)
3466
                    )
3467
                );
3468
            }
3469
            localSet = localStore.getFeatureSet(expBuilder.build(), FEATURECODE_FIELD_NAME);
3275 3470
            localIt = localSet.fastIterator();
3471
            
3276 3472
            patchGenerator.generate(remoteIt,localIt, status);
3473
            remoteChangesStore.finishEditing();
3474
            localChangesStore.finishEditing();
3277 3475
            status.terminate();
3278 3476
            return ERR_OK;
3279 3477

  
3280 3478
        } catch (UserCancelTaskException ex) {
3479
            FeatureStore.cancelEditingQuietly(remoteStore);
3480
            FeatureStore.cancelEditingQuietly(remoteChangesStore);
3481
            FeatureStore.cancelEditingQuietly(localChangesStore);
3281 3482
            status.cancel();
3282 3483
            return ERR_CANCELLED_BY_USER;
3283 3484
        } catch (Exception ex) {
3284 3485
            LOGGER.warn("Can't synchronize", ex);
3486
            FeatureStore.cancelEditingQuietly(remoteStore);
3487
            FeatureStore.cancelEditingQuietly(remoteChangesStore);
3488
            FeatureStore.cancelEditingQuietly(localChangesStore);
3285 3489
            status.abort();
3286 3490
            return ERR_SYNCHRONIZE;
3287 3491
        } finally {
......
3289 3493

  
3290 3494
            DisposeUtils.disposeQuietly(geoms);
3291 3495

  
3496
            DisposeUtils.disposeQuietly(remoteChangesStore);
3497
            DisposeUtils.disposeQuietly(localChangesStore);
3498

  
3499
            DisposeUtils.disposeQuietly(remoteIt);
3500
            DisposeUtils.disposeQuietly(remoteSet);
3292 3501
            DisposeUtils.disposeQuietly(remoteStore);
3293
            DisposeUtils.disposeQuietly(remoteSet);
3294
            DisposeUtils.disposeQuietly(remoteIt);
3295 3502
            
3503
            DisposeUtils.disposeQuietly(localIt);
3504
            DisposeUtils.disposeQuietly(localSet);
3296 3505
            DisposeUtils.disposeQuietly(localStore);
3297
            DisposeUtils.disposeQuietly(localSet);
3298
            DisposeUtils.disposeQuietly(localIt);
3299 3506
            
3507
            DisposeUtils.disposeQuietly(entitiesStore);
3508
            
3300 3509
        }
3301 3510
    }
3511

  
3512
    @Override
3513
    public WorkingArea getCurrentWorkingArea() {
3514
        return this.currentWorkingArea;
3515
    }
3516

  
3517
    @Override
3518
    public void setCurrentWorkingArea(WorkingArea workingArea) {
3519
        this.currentWorkingArea = workingArea;
3520
        VarsTable varsTable = new VarsTable();
3521
        varsTable.set(this, CONFIG_CURRENT_WORKINGAREA, workingArea.toJson().toString());
3522
    }
3523
    
3524
    private void refreshCodeGeneratorSequence(String entityName) {
3525
        OnlineEntity entity = this.getWorkspaceEntity(entityName);
3526
        long sequence = 0;
3527
        FeatureStore store = null;
3528
        try {
3529
            store = this.openFeatureStore(entity);
3530
            FeatureQuery query = store.createFeatureQuery();
3531
            query.addAggregate("MIN", entity.getFeatureIdFieldName());
3532
            Feature f = store.findFirst(query);
3533
            long l = f.getLong(entity.getFeatureIdFieldName());
3534
            if (sequence > l) {
3535
                sequence = l;
3536
            }
3537
        } catch (Exception ex) {
3538
            LOGGER.warn("Can't refresh code generator sequence");
3539
        } finally {
3540
            DisposeUtils.dispose(store);
3541
        }
3542
        this.codeGenerator.initSequence(entityName, sequence-1);
3543
    }
3544

  
3302 3545
}
3303 3546

  

Also available in: Unified diff