adding a feature.modified property, making the ModifyFeature control set it and the WFST format check for it so only modified attributes and a modified geometry need to be included in an Update transaction. r=bartvde (closes #3400)
git-svn-id: http://svn.openlayers.org/trunk/openlayers@12149 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
@@ -368,6 +368,11 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
|
|||||||
this.dragControl.activate();
|
this.dragControl.activate();
|
||||||
this.onModificationStart(this.feature);
|
this.onModificationStart(this.feature);
|
||||||
}
|
}
|
||||||
|
// keep track of geometry modifications
|
||||||
|
var modified = feature.modified;
|
||||||
|
if (feature.geometry && !(modified && modified.geometry)) {
|
||||||
|
this._originalGeometry = feature.geometry.clone();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -539,6 +544,13 @@ OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
|
|||||||
if(this.feature.state != OpenLayers.State.INSERT &&
|
if(this.feature.state != OpenLayers.State.INSERT &&
|
||||||
this.feature.state != OpenLayers.State.DELETE) {
|
this.feature.state != OpenLayers.State.DELETE) {
|
||||||
this.feature.state = OpenLayers.State.UPDATE;
|
this.feature.state = OpenLayers.State.UPDATE;
|
||||||
|
if (this.modified && this._originalGeometry) {
|
||||||
|
var feature = this.feature;
|
||||||
|
feature.modified = OpenLayers.Util.extend(feature.modified, {
|
||||||
|
geometry: this._originalGeometry
|
||||||
|
});
|
||||||
|
delete this._originalGeometry;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,42 @@ OpenLayers.Feature.Vector = OpenLayers.Class(OpenLayers.Feature, {
|
|||||||
*/
|
*/
|
||||||
renderIntent: "default",
|
renderIntent: "default",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIProperty: modified
|
||||||
|
* {Object} An object with the originals of the geometry and attributes of
|
||||||
|
* the feature, if they were changed. Currently this property is only read
|
||||||
|
* by <OpenLayers.Format.WFST.v1>, and written by
|
||||||
|
* <OpenLayers.Control.ModifyFeature>, which sets the geometry property.
|
||||||
|
* Applications can set the originals of modified attributes in the
|
||||||
|
* attributes property. Note that applications have to check if this
|
||||||
|
* object and the attributes property is already created before using it.
|
||||||
|
* After a change made with ModifyFeature, this object could look like
|
||||||
|
*
|
||||||
|
* (code)
|
||||||
|
* {
|
||||||
|
* geometry: >Object
|
||||||
|
* }
|
||||||
|
* (end)
|
||||||
|
*
|
||||||
|
* When an application has made changes to feature attributes, it could
|
||||||
|
* have set the attributes to something like this:
|
||||||
|
*
|
||||||
|
* (code)
|
||||||
|
* {
|
||||||
|
* attributes: {
|
||||||
|
* myAttribute: "original"
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* (end)
|
||||||
|
*
|
||||||
|
* Note that <OpenLayers.Format.WFST.v1> only checks for truthy values in
|
||||||
|
* *modified.geometry* and the attribute names in *modified.attributes*,
|
||||||
|
* but it is recommended to set the original values (and not just true) as
|
||||||
|
* attribute value, so applications could use this information to undo
|
||||||
|
* changes.
|
||||||
|
*/
|
||||||
|
modified: null,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor: OpenLayers.Feature.Vector
|
* Constructor: OpenLayers.Feature.Vector
|
||||||
* Create a vector feature.
|
* Create a vector feature.
|
||||||
|
|||||||
@@ -172,9 +172,24 @@ OpenLayers.Format.WFST.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
|
|||||||
* type - insert, update, or delete.
|
* type - insert, update, or delete.
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* features - {Array(<OpenLayers.Feature.Vector>)} A list of features.
|
* features - {Array(<OpenLayers.Feature.Vector>)} A list of features. See
|
||||||
|
* below for a more detailed description of the influence of the
|
||||||
|
* feature's *modified* property.
|
||||||
* options - {Object}
|
* options - {Object}
|
||||||
*
|
*
|
||||||
|
* feature.modified rules:
|
||||||
|
* If a feature has a modified property set, the following checks will be
|
||||||
|
* made before a feature's geometry or attribute is included in an Update
|
||||||
|
* transaction:
|
||||||
|
* - *modified* is not set at all: The geometry and all attributes will be
|
||||||
|
* included.
|
||||||
|
* - *modified.geometry* is truthy: The geometry will be
|
||||||
|
* included. If *modified.attributes* is not set, all attributes will
|
||||||
|
* be included.
|
||||||
|
* - *modified.attributes* is set: Only the attributes with a truthy value
|
||||||
|
* in *modified.attributes* will be included. If *modified.geometry*
|
||||||
|
* is not set, the geometry will not be included.
|
||||||
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* {String} A serialized WFS transaction.
|
* {String} A serialized WFS transaction.
|
||||||
*/
|
*/
|
||||||
@@ -276,7 +291,8 @@ OpenLayers.Format.WFST.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add in geometry
|
// add in geometry
|
||||||
if (this.geometryName !== null) {
|
var modified = feature.modified;
|
||||||
|
if (this.geometryName !== null && (!modified || modified.geometry)) {
|
||||||
this.srsName = this.getSrsName(feature);
|
this.srsName = this.getSrsName(feature);
|
||||||
this.writeNode(
|
this.writeNode(
|
||||||
"Property", {name: this.geometryName, value: feature.geometry}, node
|
"Property", {name: this.geometryName, value: feature.geometry}, node
|
||||||
@@ -285,7 +301,9 @@ OpenLayers.Format.WFST.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
|
|||||||
|
|
||||||
// add in attributes
|
// add in attributes
|
||||||
for(var key in feature.attributes) {
|
for(var key in feature.attributes) {
|
||||||
if(feature.attributes[key] !== undefined) {
|
if(feature.attributes[key] !== undefined &&
|
||||||
|
(!modified || !modified.attributes ||
|
||||||
|
(modified.attributes && modified.attributes[key]))) {
|
||||||
this.writeNode(
|
this.writeNode(
|
||||||
"Property", {name: key, value: feature.attributes[key]}, node
|
"Property", {name: key, value: feature.attributes[key]}, node
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -737,7 +737,29 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_setFeatureState(t) {
|
||||||
|
t.plan(4);
|
||||||
|
var map = new OpenLayers.Map("map");
|
||||||
|
var layer = new OpenLayers.Layer.Vector("vector", {isBaseLayer: true});
|
||||||
|
map.addLayer(layer);
|
||||||
|
var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1,2));
|
||||||
|
layer.addFeatures([feature]);
|
||||||
|
var control = new OpenLayers.Control.ModifyFeature(layer, {standalone: true});
|
||||||
|
map.addControl(control);
|
||||||
|
|
||||||
|
control.selectFeature(feature);
|
||||||
|
var originalGeometry = feature.geometry;
|
||||||
|
|
||||||
|
t.ok(control._originalGeometry, "original geometry stored for later use in setFeatureState");
|
||||||
|
|
||||||
|
feature.geometry = new OpenLayers.Geometry.Point(2,3);
|
||||||
|
control.modified = true;
|
||||||
|
control.setFeatureState();
|
||||||
|
|
||||||
|
t.eq(feature.state, OpenLayers.State.UPDATE, "feature state set to UPDATE");
|
||||||
|
t.geom_eq(feature.modified.geometry, originalGeometry, "original geometry stored on the modified property");
|
||||||
|
t.eq(control._originalGeometry, undefined, "original geometry deleted once it is set on the modified property");
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
deleteFeature.state = OpenLayers.State.DELETE;
|
deleteFeature.state = OpenLayers.State.DELETE;
|
||||||
deleteFeature.fid = "fid.37";
|
deleteFeature.fid = "fid.37";
|
||||||
|
|
||||||
t.plan(5);
|
t.plan(7);
|
||||||
var snippets = {
|
var snippets = {
|
||||||
"GetFeature": {maxFeatures: 1, outputFormat: 'json'},
|
"GetFeature": {maxFeatures: 1, outputFormat: 'json'},
|
||||||
"Transaction": null,
|
"Transaction": null,
|
||||||
@@ -61,6 +61,19 @@
|
|||||||
var got = format.writers["wfs"][snippet].apply(format, [arg]);
|
var got = format.writers["wfs"][snippet].apply(format, [arg]);
|
||||||
t.xml_eq(got, expected, snippet + " request created correctly");
|
t.xml_eq(got, expected, snippet + " request created correctly");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateFeature.modified = {geometry: updateFeature.geometry.clone()};
|
||||||
|
updateFeature.geometry = new OpenLayers.Geometry.Point(2,3);
|
||||||
|
var expected = readXML("UpdateModified");
|
||||||
|
var got = format.writers["wfs"]["Update"].apply(format, [updateFeature]);
|
||||||
|
t.xml_eq(got, expected, "Update request for feature with modified geometry created correctly");
|
||||||
|
|
||||||
|
updateFeature.modified.attributes = {foo: "bar"};
|
||||||
|
updateFeature.attributes.foo = "baz";
|
||||||
|
delete updateFeature.modified.geometry;
|
||||||
|
var expected = readXML("UpdateModifiedNoGeometry");
|
||||||
|
var got = format.writers["wfs"]["Update"].apply(format, [updateFeature]);
|
||||||
|
t.xml_eq(got, expected, "Update request for feature with no modified geometry but modified attributes created correctly");
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_writeNative(t) {
|
function test_writeNative(t) {
|
||||||
@@ -264,6 +277,39 @@
|
|||||||
</ogc:Filter>
|
</ogc:Filter>
|
||||||
</wfs:Update>
|
</wfs:Update>
|
||||||
--></div>
|
--></div>
|
||||||
|
<div id="UpdateModified"><!--
|
||||||
|
<wfs:Update xmlns:wfs="http://www.opengis.net/wfs" typeName="topp:states" xmlns:topp="http://www.openplans.org/topp">
|
||||||
|
<wfs:Property>
|
||||||
|
<wfs:Name>the_geom</wfs:Name>
|
||||||
|
<wfs:Value>
|
||||||
|
<gml:Point xmlns:gml="http://www.opengis.net/gml">
|
||||||
|
<gml:coordinates decimal="." cs="," ts=" ">2,3</gml:coordinates>
|
||||||
|
</gml:Point>
|
||||||
|
</wfs:Value>
|
||||||
|
</wfs:Property>
|
||||||
|
<wfs:Property>
|
||||||
|
<wfs:Name>foo</wfs:Name>
|
||||||
|
<wfs:Value>bar</wfs:Value>
|
||||||
|
</wfs:Property>
|
||||||
|
<wfs:Property>
|
||||||
|
<wfs:Name>nul</wfs:Name>
|
||||||
|
</wfs:Property>
|
||||||
|
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
|
||||||
|
<ogc:FeatureId fid="fid.42"/>
|
||||||
|
</ogc:Filter>
|
||||||
|
</wfs:Update>
|
||||||
|
--></div>
|
||||||
|
<div id="UpdateModifiedNoGeometry"><!--
|
||||||
|
<wfs:Update xmlns:wfs="http://www.opengis.net/wfs" typeName="topp:states" xmlns:topp="http://www.openplans.org/topp">
|
||||||
|
<wfs:Property>
|
||||||
|
<wfs:Name>foo</wfs:Name>
|
||||||
|
<wfs:Value>baz</wfs:Value>
|
||||||
|
</wfs:Property>
|
||||||
|
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
|
||||||
|
<ogc:FeatureId fid="fid.42"/>
|
||||||
|
</ogc:Filter>
|
||||||
|
</wfs:Update>
|
||||||
|
--></div>
|
||||||
<div id="Delete"><!--
|
<div id="Delete"><!--
|
||||||
<wfs:Delete xmlns:wfs="http://www.opengis.net/wfs" typeName="topp:states" xmlns:topp="http://www.openplans.org/topp">
|
<wfs:Delete xmlns:wfs="http://www.opengis.net/wfs" typeName="topp:states" xmlns:topp="http://www.openplans.org/topp">
|
||||||
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
|
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
|
||||||
|
|||||||
Reference in New Issue
Block a user