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