Ticket #1699: patch-1699-r7875-A0.diff
| File patch-1699-r7875-A0.diff, 48.2 kB (added by elemoine, 2 years ago) |
|---|
-
build/license.txt
old new 52 52 * You may obtain a copy of the License at 53 53 * http://www.apache.org/licenses/LICENSE-2.0 54 54 */ 55 56 /** 57 * Contains portions of Gears <http://code.google.com/apis/gears/> 58 * 59 * Copyright 2007, Google Inc. 60 * 61 * Redistribution and use in source and binary forms, with or without 62 * modification, are permitted provided that the following conditions are met: 63 * 64 * 1. Redistributions of source code must retain the above copyright notice, 65 * this list of conditions and the following disclaimer. 66 * 2. Redistributions in binary form must reproduce the above copyright notice, 67 * this list of conditions and the following disclaimer in the documentation 68 * and/or other materials provided with the distribution. 69 * 3. Neither the name of Google Inc. nor the names of its contributors may be 70 * used to endorse or promote products derived from this software without 71 * specific prior written permission. 72 * 73 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 74 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 75 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 76 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 77 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 78 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 79 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 80 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 81 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 82 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 83 * 84 * Sets up google.gears.*, which is *the only* supported way to access Gears. 85 * 86 * Circumvent this file at your own risk! 87 * 88 * In the future, Gears may automatically define google.gears.* without this 89 * file. Gears may use these objects to transparently fix bugs and compatibility 90 * issues. Applications that use the code below will continue to work seamlessly 91 * when that happens. 92 */ -
tests/Protocol/SQL/Gears.html
old new 1 <html> 2 <head> 3 <script src="../../../lib/OpenLayers.js"></script> 4 <script type="text/javascript"> 5 6 function test_initialize(t) { 7 var protocol = new OpenLayers.Protocol.SQL.Gears(); 8 if (!protocol.supported()) { 9 t.plan(0); 10 return; 11 } 12 13 t.plan(5); 14 15 t.eq(protocol.CLASS_NAME, "OpenLayers.Protocol.SQL.Gears", 16 "ctor returns correct value"); 17 18 t.eq(protocol.jsonParser.CLASS_NAME, 19 "OpenLayers.Format.JSON", 20 "ctor creates a JSON parser"); 21 22 t.eq(protocol.wktParser.CLASS_NAME, 23 "OpenLayers.Format.WKT", 24 "ctor creates a WKT parser"); 25 26 var str = protocol.FID_PREFIX + "foo_bar"; 27 t.ok(str.match(protocol.fidRegExp), 28 "ctor creates correct regexp"); 29 30 t.ok(typeof protocol.db == "object", 31 "ctor creates a db object"); 32 33 protocol.clear(); 34 protocol.destroy(); 35 } 36 37 function test_destroy(t) { 38 var protocol = new OpenLayers.Protocol.SQL.Gears(); 39 if (!protocol.supported()) { 40 t.plan(0); 41 return; 42 } 43 44 t.plan(3); 45 46 protocol.destroy(); 47 48 t.eq(protocol.db, null, 49 "destroy nullifies db"); 50 t.eq(protocol.jsonParser, null, 51 "destroy nullifies jsonParser"); 52 t.eq(protocol.wktParser, null, 53 "destroy nullifies wktParser"); 54 } 55 56 function test_read(t) { 57 var protocolCallback, readCallback; 58 var protocolOptions = {callback: protocolCallback}; 59 var readOptions = {callback: readCallback}; 60 61 var protocol = new OpenLayers.Protocol.SQL.Gears(protocolOptions); 62 if (!protocol.supported()) { 63 t.plan(0); 64 return; 65 } 66 67 function okCallback(resp) { 68 t.eq(resp.CLASS_NAME, "OpenLayers.Protocol.Response", 69 "read calls correct callback with a response object"); 70 } 71 72 function failCallback(resp) { 73 t.fail("read calls incorrect callback"); 74 } 75 76 t.plan(4); 77 78 var resp; 79 80 // 2 tests 81 protocolOptions.callback = okCallback; 82 readOptions.callback = failCallback; 83 resp = protocol.read(); 84 t.eq(resp.CLASS_NAME, "OpenLayers.Protocol.Response", 85 "read returns a response object"); 86 87 // 2 test 88 protocolOptions.callback = failCallback; 89 readOptions.callback = okCallback; 90 resp = protocol.read(readOptions); 91 t.eq(resp.CLASS_NAME, "OpenLayers.Protocol.Response", 92 "read returns a response object"); 93 94 protocol.clear(); 95 protocol.destroy(); 96 } 97 98 function test_unfreezeFeature(t) { 99 var protocol = new OpenLayers.Protocol.SQL.Gears(); 100 if (!protocol.supported()) { 101 t.plan(0); 102 return; 103 } 104 105 t.plan(10); 106 107 var feature; 108 var wkt, json, fid, state; 109 110 json = "{\"fake\":\"properties\"}"; 111 fid = "1000"; 112 state = OpenLayers.State.INSERT; 113 114 var row = { 115 fieldByName: function(str) { 116 if (str == "geometry") { 117 return wkt; 118 } 119 if (str == "properties") { 120 return json; 121 } 122 if (str == "fid") { 123 return fid; 124 } 125 if (str == "state") { 126 return state; 127 } 128 } 129 }; 130 131 // 5 tests 132 wkt = "POINT(1 2)"; 133 feature = protocol.unfreezeFeature(row); 134 t.eq(feature.CLASS_NAME, "OpenLayers.Feature.Vector", 135 "unfreezeFeature returns an OpenLayers.Feature.Vector"); 136 t.ok(feature.geometry.x == 1 && feature.geometry.y == 2, 137 "unfreezeFeature returns a feature with correct geometry"); 138 t.eq(feature.attributes.fake, "properties", 139 "unfreezeFeature returns a feature with correct attributes"); 140 t.eq(feature.fid, fid, 141 "unfreezeFeature returns a feature with fid"); 142 t.eq(feature.state, state, 143 "unfreezeFeature returns a feature with state"); 144 145 // 5 tests 146 wkt = protocol.NULL_GEOMETRY; 147 state = protocol.NULL_FEATURE_STATE; 148 feature = protocol.unfreezeFeature(row); 149 t.eq(feature.CLASS_NAME, "OpenLayers.Feature.Vector", 150 "unfreezeFeature returns an OpenLayers.Feature.Vector"); 151 t.eq(feature.geometry, null, 152 "unfreezeFeature returns a feature with correct geometry"); 153 t.eq(feature.attributes.fake, "properties", 154 "unfreezeFeature returns a feature with correct attributes"); 155 t.eq(feature.fid, fid, 156 "unfreezeFeature returns a feature with fid"); 157 t.eq(feature.state, null, 158 "unfreezeFeature returns a feature with state"); 159 160 protocol.clear(); 161 protocol.destroy(); 162 } 163 164 function test_extractFidFromField(t) { 165 var protocol = new OpenLayers.Protocol.SQL.Gears(); 166 if (!protocol.supported()) { 167 t.plan(0); 168 return; 169 } 170 171 t.plan(4); 172 173 var field, fid; 174 175 // fid is a string, field is not prefixed with FID_PREFIX 176 // 1 test 177 field = "10"; 178 res = protocol.extractFidFromField(field); 179 t.eq(res, "10", 180 "extractFidFromField returns expected string"); 181 182 // fid is a string, field is prefixed with FID_PREFIX 183 // 1 test 184 field = protocol.FIX_PREFIX + "10"; 185 res = protocol.extractFidFromField(field); 186 t.eq(res, protocol.FIX_PREFIX + "10", 187 "extractFidFromField returns expected prefixed string"); 188 189 // fid is a number, field is not prefixed with FIX_PREFIX 190 // 1 test 191 protocol.typeOfFid = "number"; 192 field = "10"; 193 res = protocol.extractFidFromField(field); 194 t.eq(res, 10, 195 "extractFidFromField returns expected number"); 196 197 // fid is a number, field is prefixed with FIX_PREFIX 198 // 1 test 199 protocol.typeOfFid = "number"; 200 field = protocol.FID_PREFIX + "10"; 201 res = protocol.extractFidFromField(field); 202 t.eq(res, protocol.FID_PREFIX + "10", 203 "extractFidFromField returns expected prefixed string"); 204 } 205 206 function test_freezeFeature(t) { 207 var protocol = new OpenLayers.Protocol.SQL.Gears(); 208 if (!protocol.supported()) { 209 t.plan(0); 210 return; 211 } 212 213 t.plan(8); 214 215 var feature, res; 216 217 // 4 tests 218 feature = new OpenLayers.Feature.Vector(); 219 feature.geometry = new OpenLayers.Geometry.Point(1, 2); 220 feature.attributes.fake = "properties"; 221 feature.fid = "1000"; 222 feature.state = OpenLayers.State.INSERT; 223 res = protocol.freezeFeature(feature); 224 t.eq(res[0], feature.fid, 225 "freezeFeature returns correct fid"); 226 t.eq(res[1], "POINT(1 2)", 227 "freezeFeature returns correct WKT"); 228 t.eq(res[2], "{\"fake\":\"properties\"}", 229 "freezeFeature returns correct JSON"); 230 t.eq(res[3], feature.state, 231 "freezeFeature returns correct feature state"); 232 233 // 4 tests 234 protocol.saveFeatureState = false; 235 feature = new OpenLayers.Feature.Vector(); 236 feature.attributes.fake = "properties"; 237 feature.fid = "1000"; 238 feature.state = OpenLayers.State.INSERT; 239 res = protocol.freezeFeature(feature); 240 t.eq(res[0], feature.fid, 241 "freezeFeature returns correct fid"); 242 t.eq(res[1], protocol.NULL_GEOMETRY, 243 "freezeFeature returns expected null geom string"); 244 t.eq(res[2], "{\"fake\":\"properties\"}", 245 "freezeFeature returns correct JSON"); 246 t.eq(res[3], protocol.NULL_FEATURE_STATE, 247 "freezeFeature returns expected null feature state string"); 248 249 protocol.clear(); 250 protocol.destroy(); 251 } 252 253 function test_createOrUpdate(t) { 254 var protocol = new OpenLayers.Protocol.SQL.Gears(); 255 if (!protocol.supported()) { 256 t.plan(0); 257 return; 258 } 259 260 t.plan(8); 261 262 var resp; 263 var scope = {"fake": "scope"}; 264 var requestType = "create"; 265 266 var options = { 267 callback: function(resp) { 268 t.eq(resp.CLASS_NAME, "OpenLayers.Protocol.Response", 269 "user callback is passed a response"); 270 t.eq(resp.requestType, requestType, 271 "user callback is passed correct request type in resp"); 272 t.ok(this == scope, 273 "user callback called with correct scope"); 274 }, 275 scope: scope 276 }; 277 278 // 4 tests 279 var feature = new OpenLayers.Feature.Vector(); 280 feature.fid = "1000"; 281 feature.attributes.fake = "properties"; 282 feature.state = OpenLayers.State.INSERT; 283 resp = protocol.createOrUpdate([feature], options, requestType); 284 t.eq(resp.CLASS_NAME, "OpenLayers.Protocol.Response", 285 "createOrUpdate returns a response"); 286 287 // check what we have in the DB 288 // 4 tests 289 resp = protocol.read(); 290 t.eq(resp.features.length, 1, 291 "createOrUpdate inserts feature in the DB"); 292 t.eq(resp.features[0].fid, feature.fid, 293 "createOrUpdate inserts feature with correct fid"); 294 t.eq(resp.features[0].attributes.fake, feature.attributes.fake, 295 "createOrUpdate inserts feature with correct attributes"); 296 t.eq(resp.features[0].state, feature.state, 297 "createOrUpdate inserts feature with correct state"); 298 299 protocol.clear(); 300 protocol.destroy(); 301 } 302 303 function test_delete(t) { 304 var protocol = new OpenLayers.Protocol.SQL.Gears(); 305 if (!protocol.supported()) { 306 t.plan(0); 307 return; 308 } 309 310 t.plan(4); 311 312 function createOneAndDeleteOne(fid, deleteOptions) { 313 var feature = new OpenLayers.Feature.Vector(); 314 feature.fid = fid; 315 feature.attributes.fake = "properties"; 316 feature.state = OpenLayers.State.INSERT; 317 var r = protocol.create([feature]); 318 protocol["delete"](r.reqFeatures, deleteOptions); 319 } 320 321 var resp, fid; 322 323 // 1 test 324 fid = 1000; 325 createOneAndDeleteOne(fid) 326 resp = protocol.read(); 327 t.eq(resp.features.length, 0, 328 "delete deletes feature in the DB"); 329 protocol.clear(); 330 331 // 1 test 332 fid = 1000; 333 createOneAndDeleteOne(fid, {dontDelete: true}); 334 resp = protocol.read(); 335 t.eq(resp.features.length, 1, 336 "delete does not delete feature if dontDelete is true"); 337 protocol.clear(); 338 339 // 1 test 340 fid = "1000"; 341 createOneAndDeleteOne(fid, {dontDelete: true}); 342 resp = protocol.read(); 343 t.eq(resp.features.length, 1, 344 "delete does not delete feature if dontDelete is true"); 345 protocol.clear(); 346 347 // 1 test 348 fid = protocol.FID_PREFIX + "1000"; 349 createOneAndDeleteOne(fid, {dontDelete: true}); 350 resp = protocol.read(); 351 t.eq(resp.features.length, 0, 352 "delete deletes feature if dontDelete is true and fid is prefixed"); 353 protocol.clear(); 354 355 protocol.destroy(); 356 } 357 358 function test_callUserCallback(t) { 359 var protocol = new OpenLayers.Protocol.SQL.Gears(); 360 if (!protocol.supported()) { 361 t.plan(0); 362 return; 363 } 364 365 t.plan(6); 366 367 var options, resp; 368 var scope = {'fake': 'scope'}; 369 370 // test commit callback 371 // 1 tests 372 options = { 373 'callback': function() { 374 t.ok(this == scope, 'callback called with correct scope'); 375 }, 376 'scope': scope 377 }; 378 resp = {'requestType': 'create', 'last': true}; 379 protocol.callUserCallback(options, resp); 380 // 0 test 381 resp = {'requestType': 'create', 'last': false}; 382 protocol.callUserCallback(options, resp); 383 384 // test create callback 385 // 2 tests 386 options = { 387 'create': { 388 'callback': function(r) { 389 t.ok(this == scope, 'callback called with correct scope'); 390 t.ok(r == resp, 'callback called with correct response'); 391 }, 392 'scope': scope 393 } 394 }; 395 resp = {'requestType': 'create'}; 396 protocol.callUserCallback(options, resp); 397 398 // test with both callbacks set 399 // 3 tests 400 options = { 401 'create': { 402 'callback': function(r) { 403 t.ok(this == scope, 'callback called with correct scope'); 404 t.ok(r == resp, 'callback called with correct response'); 405 }, 406 'scope': scope 407 }, 408 'callback': function() { 409 t.ok(this == scope, 'callback called with correct scope'); 410 }, 411 'scope': scope 412 }; 413 resp = {'requestType': 'create', 'last': true}; 414 protocol.callUserCallback(options, resp); 415 416 // no callback set 417 // 0 test 418 options = { 419 'delete': { 420 'callback': function(resp) { 421 t.fail('callback should not get called'); 422 } 423 } 424 }; 425 resp = {'requestType': 'create'}; 426 protocol.callUserCallback(options, resp); 427 428 // cleanup 429 protocol.destroy(); 430 } 431 432 </script> 433 </head> 434 <body> 435 </body> 436 </html> -
tests/Protocol/SQL.html
old new 1 <html> 2 <head> 3 <script src="../../lib/OpenLayers.js"></script> 4 <script type="text/javascript"> 5 6 function test_initialize(t) { 7 t.plan(3); 8 var options = {tableName: 'my_features', 9 databaseName: 'my_database_name'} 10 var protocol = new OpenLayers.Protocol.SQL(options); 11 12 t.ok(protocol instanceof OpenLayers.Protocol.SQL, 13 "new OpenLayers.Protocol.SQL returns object"); 14 15 t.eq(protocol.tableName, options.tableName, "tableName property is set"); 16 t.eq(protocol.databaseName, options.databaseName, "databaseName property is set"); 17 } 18 19 </script> 20 </head> 21 <body> 22 </body> 23 </html> -
tests/list-tests.html
old new 113 113 <li>Popup/FramedCloud.html</li> 114 114 <li>Projection.html</li> 115 115 <li>Protocol.html</li> 116 <li>Protocol/SQL.html</li> 117 <li>Protocol/SQL/Gears.html</li> 116 118 <li>Renderer.html</li> 117 119 <li>Renderer/Canvas.html</li> 118 120 <li>Renderer/Elements.html</li> -
lib/OpenLayers/Protocol/SQL/Gears.js
old new 1 /* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD 2 * license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the 3 * full text of the license. */ 4 5 /** 6 * @requires Gears/gears_init.js 7 * @requires OpenLayers/Protocol/SQL.js 8 * @requires OpenLayers/Format/JSON.js 9 * @requires OpenLayers/Format/WKT.js 10 */ 11 12 /** 13 * Class: OpenLayers.Protocol.SQL.Gears 14 * This Protocol stores feature in the browser via the Gears Database module 15 * <http://code.google.com/apis/gears/api_database.html>. 16 * 17 * The main advantage is that all the read, create, update and delete operations 18 * can be done offline. 19 * 20 * Inherits from: 21 * - <OpenLayers.Protocol.SQL> 22 */ 23 OpenLayers.Protocol.SQL.Gears = OpenLayers.Class(OpenLayers.Protocol.SQL, { 24 25 /** 26 * Property: FID_PREFIX 27 * {String} 28 */ 29 FID_PREFIX: '__gears_fid__', 30 31 /** 32 * Property: NULL_GEOMETRY 33 * {String} 34 */ 35 NULL_GEOMETRY: '__gears_null_geometry__', 36 37 /** 38 * Property: NULL_FEATURE_STATE 39 * {String} 40 */ 41 NULL_FEATURE_STATE: '__gears_null_feature_state__', 42 43 /** 44 * Property: jsonParser 45 * {<OpenLayers.Format.JSON>} 46 */ 47 jsonParser: null, 48 49 /** 50 * Property: wktParser 51 * {<OpenLayers.Format.WKT>} 52 */ 53 wktParser: null, 54 55 /** 56 * Property: fidRegExp 57 * {RegExp} Regular expression to know whether a feature was 58 * created in offline mode. 59 */ 60 fidRegExp: null, 61 62 /** 63 * Property: saveFeatureState 64 * {Boolean} Whether to save the feature state (<OpenLayers.State>) 65 * into the database. 66 */ 67 saveFeatureState: true, 68 69 /** 70 * Property: typeOfFid 71 * {String} The type of the feature identifier, either "number" or 72 * "string", defaults to "string". 73 */ 74 typeOfFid: "string", 75 76 /** 77 * Property: db 78 * {GearsDatabase} 79 */ 80 db: null, 81 82 /** 83 * Constructor: OpenLayers.Protocol.SQL.Gears 84 */ 85 initialize: function(options) { 86 if (!this.supported()) { 87 return; 88 } 89 OpenLayers.Protocol.SQL.prototype.initialize.apply(this, [options]); 90 this.jsonParser = new OpenLayers.Format.JSON(); 91 this.wktParser = new OpenLayers.Format.WKT(); 92 93 this.fidRegExp = new RegExp('^' + this.FID_PREFIX); 94 this.initializeDatabase(); 95 96 97 }, 98 99 /** 100 * Method: initializeDatabase 101 */ 102 initializeDatabase: function() { 103 this.db = google.gears.factory.create('beta.database'); 104 this.db.open(this.databaseName); 105 this.db.execute( 106 "CREATE TABLE IF NOT EXISTS " + this.tableName + 107 " (fid TEXT UNIQUE, geometry TEXT, properties TEXT," + 108 " state TEXT)"); 109 }, 110 111 /** 112 * APIMethod: destroy 113 * Clean up the protocol. 114 */ 115 destroy: function() { 116 this.db.close(); 117 this.db = null; 118 119 this.jsonParser = null; 120 this.wktParser = null; 121 122 OpenLayers.Protocol.SQL.prototype.destroy.apply(this); 123 }, 124 125 /** 126 * APIMethod: supported 127 * Determine whether a browser supports Gears 128 * 129 * Returns: 130 * {Boolean} The browser supports Gears 131 */ 132 supported: function() { 133 return !!(window.google && google.gears); 134 }, 135 136 /** 137 * Method: read 138 * Read all features from the database and return a 139 * <OpenLayers.Protocol.Response> instance. If the options parameter 140 * contains a callback attribute, the function is called with the response 141 * as a parameter. 142 * 143 * Parameters: 144 * options - {Object} Optional parameter that may contain a callback 145 * attribute. 146 * 147 * Returns: 148 * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response> 149 * object. 150 */ 151 read: function(options) { 152 options = OpenLayers.Util.applyDefaults(options, this.options); 153 154 var features = []; 155 var rs = this.db.execute("SELECT * FROM " + this.tableName); 156 while (rs.isValidRow()) { 157 features.push(this.unfreezeFeature(rs)); 158 rs.next(); 159 } 160 rs.close(); 161 162 var resp = new OpenLayers.Protocol.Response({ 163 code: OpenLayers.Protocol.Response.SUCCESS, 164 requestType: "read", 165 features: features 166 }); 167 168 if (options && options.callback) { 169 options.callback.call(options.scope, resp); 170 } 171 172 return resp; 173 }, 174 175 /** 176 * Method: unfreezeFeature 177 * 178 * Parameters: 179 * row - {ResultSet} 180 * 181 * Returns: 182 * {<OpenLayers.Feature.Vector>} 183 */ 184 unfreezeFeature: function(row) { 185 var feature; 186 var wkt = row.fieldByName('geometry'); 187 if (wkt == this.NULL_GEOMETRY) { 188 feature = new OpenLayers.Feature.Vector(); 189 } else { 190 feature = this.wktParser.read(wkt); 191 } 192 193 feature.attributes = this.jsonParser.read( 194 row.fieldByName('properties')); 195 196 feature.fid = this.extractFidFromField(row.fieldByName('fid')); 197 198 var state = row.fieldByName('state'); 199 if (state == this.NULL_FEATURE_STATE) { 200 state = null; 201 } 202 feature.state = state; 203 204 return feature; 205 }, 206 207 /** 208 * Method: extractFidFromField 209 * 210 * Parameters: 211 * field - {String} 212 * 213 * Returns 214 * {String} or {Number} The fid. 215 */ 216 extractFidFromField: function(field) { 217 if (!field.match(this.fidRegExp) && this.typeOfFid == "number") { 218 field = parseFloat(field); 219 } 220 return field; 221 }, 222 223 /** 224 * Method: create 225 * Create new features into the database. 226 * 227 * Parameters: 228 * features - {Array({<OpenLayers.Feature.Vector>})} or 229 * {<OpenLayers.Feature.Vector>}. 230 * options - {Object} Optional object for configuring the request. 231 * 232 * Returns: 233 * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response> 234 * object. 235 */ 236 create: function(features, options) { 237 return this.createOrUpdate(features, options, "create"); 238 }, 239 240 /** 241 * Method: update 242 * Construct a request updating modified feature. 243 * 244 * Parameters: 245 * features - {Array({<OpenLayers.Feature.Vector>})} or 246 * {<OpenLayers.Feature.Vector>}. 247 * options - {Object} Optional object for configuring the request. 248 * 249 * Returns: 250 * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response> 251 * object. 252 */ 253 update: function(features, options) { 254 return this.createOrUpdate(features, options, "update"); 255 }, 256 257 /** 258 * Method: createOrUpdate 259 * Construct a request for updating or creating features in the 260 * database. 261 * 262 * Parameters: 263 * features - {Array({<OpenLayers.Feature.Vector>})} or 264 * {<OpenLayers.Feature.Vector>}. 265 * options - {Object} Optional object for configuring the request. 266 * requestType - {String} Either "create" or "update". 267 * 268 * Returns: 269 * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response> 270 * object. 271 */ 272 createOrUpdate: function(features, options, requestType) { 273 if (!(features instanceof Array)) { 274 features = [features]; 275 } 276 277 options = OpenLayers.Util.applyDefaults(options, this.options); 278 279 var i, len = features.length, feature; 280 var insertedFeatures = new Array(len); 281 282 for (i = 0; i < len; i++) { 283 feature = features[i]; 284 this.db.execute( 285 "REPLACE INTO " + this.tableName + 286 " (fid, geometry, properties, state)" + 287 " VALUES (?, ?, ?, ?)", 288 this.freezeFeature(feature) 289 ); 290 var clone = feature.clone(); 291 clone.fid = feature.fid; 292 insertedFeatures[i] = clone; 293 } 294 295 var resp = new OpenLayers.Protocol.Response({ 296 code: OpenLayers.Protocol.Response.SUCCESS, 297 requestType: requestType, 298 features: insertedFeatures, 299 reqFeatures: features 300 }); 301 302 if (options && options.callback) { 303 options.callback.call(options.scope, resp); 304 } 305 306 return resp; 307 }, 308 309 /** 310 * Method: freezeFeature 311 * 312 * Parameters: 313 * feature - {<OpenLayers.Feature.Vector>} 314 * 315 * Returns: 316 * {Array} 317 */ 318 freezeFeature: function(feature) { 319 feature.fid = feature.fid != null ? 320 feature.fid : OpenLayers.Util.createUniqueID(this.FID_PREFIX); 321 322 var geometry = feature.geometry ? 323 feature.geometry.toString() : this.NULL_GEOMETRY; 324 var state = this.saveFeatureState ? 325 feature.state : this.NULL_FEATURE_STATE; 326 327 return [ 328 feature.fid, 329 geometry, 330 this.jsonParser.write(feature.attributes), 331 state 332 ]; 333 }, 334 335 /** 336 * Method: delete 337 * Delete features from the database. 338 * 339 * Parameters: 340 * features - {Array({<OpenLayers.Feature.Vector>})} or 341 * {<OpenLayers.Feature.Vector>} 342 * options - {Object} Optional object for configuring the request, it 343 * may include a dontDelete property that indicates whether a 344 * feature that wasn't created offline must actually be deleted 345 * from the database or just be updated (with its new state). 346 * This object is modified and should not be reused. 347 * 348 * Returns: 349 * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response> 350 * object. 351 */ 352 "delete": function(features, options) { 353 if (!(features instanceof Array)) { 354 features = [features]; 355 } 356 357 options = OpenLayers.Util.applyDefaults(options, this.options); 358 359 var i, len, feature; 360 for (i = 0, len = features.length; i < len; i++) { 361 feature = features[i]; 362 363 // if the dontDelete flag is set in the options and if the feature 364 // wasn't created offline then don't delete it in the database 365 var doDelete = (typeof feature.fid == 'string' && 366 !!(feature.fid.match(this.fidRegExp))); 367 if (options.dontDelete && !doDelete) { 368 var toDelete = feature.clone(); 369 toDelete.fid = feature.fid; 370 if (toDelete.geometry) { 371 toDelete.geometry.destroy(); 372 toDelete.geometry = null; 373 } 374 toDelete.state = feature.state; 375 376 this.update(toDelete); 377 } else { 378 this.db.execute( 379 "DELETE FROM " + this.tableName + 380 " WHERE fid = ?", [feature.fid]); 381 } 382 } 383 384 var resp = new OpenLayers.Protocol.Response({ 385 code: OpenLayers.Protocol.Response.SUCCESS, 386 requestType: "delete", 387 reqFeatures: features 388 }); 389 390 if (options && options.callback) { 391 options.callback.call(options.scope, resp); 392 } 393 394 return resp; 395 }, 396 397 /** 398 * Method: commit 399 * Go over the features and for each take action 400 * based on the feature state. Possible actions are create, 401 * update and delete. 402 * 403 * Parameters: 404 * features - {Array({<OpenLayers.Feature.Vector>})} 405 * options - {Object} Object whose possible keys are "create", "update", 406 * "delete", "callback" and "scope", the values referenced by the 407 * first three are objects as passed to the "create", "update", and 408 * "delete" methods, the value referenced by the "callback" key is 409 * a function which is called when the commit operation is complete 410 * using the scope referenced by the "scope" key. 411 * 412 * Returns: 413 * {Array({<OpenLayers.Protocol.Response>})} An array of 414 * <OpenLayers.Protocol.Response> objects, one per request made 415 * to the database. 416 */ 417 commit: function(features, options) { 418 var opt, resp = [], nRequests = 0, nResponses = 0; 419 420 function callback(resp) { 421 if (++nResponses < nRequests) { 422 resp.last = false; 423 } 424 this.callUserCallback(options, resp); 425 } 426 427 var feature, toCreate = [], toUpdate = [], toDelete = []; 428 for (var i = features.length - 1; i >= 0; i--) { 429 feature = features[i]; 430 switch (feature.state) { 431 case OpenLayers.State.INSERT: 432 toCreate.push(feature); 433 break; 434 case OpenLayers.State.UPDATE: 435 toUpdate.push(feature); 436 break; 437 case OpenLayers.State.DELETE: 438 toDelete.push(feature); 439 break; 440 } 441 } 442 if (toCreate.length > 0) { 443 nRequests++; 444 opt = OpenLayers.Util.applyDefaults( 445 {"callback": callback, "scope": this}, 446 options.create 447 ); 448 resp.push(this.create(toCreate, opt)); 449 } 450 if (toUpdate.length > 0) { 451 nRequests++; 452 opt = OpenLayers.Util.applyDefaults( 453 {"callback": callback, "scope": this}, 454 options.update 455 ); 456 resp.push(this.update(toUpdate, opt)); 457 } 458 if (toDelete.length > 0) { 459 nRequests++; 460 opt = OpenLayers.Util.applyDefaults( 461 {"callback": callback, "scope": this}, 462 options["delete"] 463 ); 464 resp.push(this["delete"](toDelete, opt)); 465 } 466 467 return resp; 468 }, 469 470 /** 471 * Method: clear 472 * Removes all rows of the table. 473 */ 474 clear: function() { 475 this.db.execute("DELETE FROM " + this.tableName); 476 }, 477 478 /** 479 * Method: callUserCallback 480 * This method is called from within commit each time a request is made 481 * to the database, it is responsible for calling the user-supplied 482 * callbacks. 483 * 484 * Parameters: 485 * options - {Object} The map of options passed to the commit call. 486 * resp - {<OpenLayers.Protocol.Response>} 487 */ 488 callUserCallback: function(options, resp) { 489 var opt = options[resp.requestType]; 490 if (opt && opt.callback) { 491 opt.callback.call(opt.scope, resp); 492 } 493 if (resp.last && options.callback) { 494 options.callback.call(options.scope); 495 } 496 }, 497 498 CLASS_NAME: "OpenLayers.Protocol.SQL.Gears" 499 }); -
lib/OpenLayers/Protocol/SQL.js
old new 1 /* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD 2 * license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the 3 * full text of the license. */ 4 5 /** 6 * @requires OpenLayers/Protocol.js 7 */ 8 9 /** 10 * Class: OpenLayers.Protocol.SQL 11 * Abstract SQL protocol class. Not to be instantiated directly. Use 12 * one of the SQL protocol subclasses instead. 13 * 14 * Inherits from: 15 * - <OpenLayers.Protocol> 16 */ 17 OpenLayers.Protocol.SQL = OpenLayers.Class(OpenLayers.Protocol, { 18 19 /** 20 * APIProperty: databaseName 21 * {String} 22 */ 23 databaseName: 'ol', 24 25 /** 26 * APIProperty: tableName 27 * Name of the database table into which Features should be saved. 28 */ 29 tableName: "ol_vector_features", 30 31 /** 32 * Constructor: OpenLayers.Protocol.SQL 33 */ 34 initialize: function(options) { 35 OpenLayers.Protocol.prototype.initialize.apply(this, [options]); 36 }, 37 38 /** 39 * APIMethod: destroy 40 * Clean up the protocol. 41 */ 42 destroy: function() { 43 OpenLayers.Protocol.prototype.destroy.apply(this); 44 }, 45 46 /** 47 * APIMethod: supported 48 * This should be overridden by specific subclasses 49 * 50 * Returns: 51 * {Boolean} Whether or not the browser supports the SQL backend 52 */ 53 supported: function() { 54 return false; 55 }, 56 57 CLASS_NAME: "OpenLayers.Protocol.SQL" 58 }); 59 60 61 /** 62 * APIFunction: factory. 63 * Alternative constructor 64 */ 65 OpenLayers.Protocol.SQL.factory = function(options) { 66 // Available SQL backends. 67 var sqls = ["Gears"]; 68 69 for (var i = 0; i < sqls.length; i++) { 70 var sql = OpenLayers.Protocol.SQL[sqls[i]]; 71 if (sql && sql.prototype.supported()) { 72 return new sql(options); 73 } 74 OpenLayers.Console.userError("No SQL backend supported ..."); 75 } 76 } -
lib/Gears/gears_init.js
old new 1 /* 2 * Copyright 2007, Google Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * 1. Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright notice, 10 * this list of conditions and the following disclaimer in the documentation 11 * and/or other materials provided with the distribution. 12 * 3. Neither the name of Google Inc. nor the names of its contributors may be 13 * used to endorse or promote products derived from this software without 14 * specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 * Sets up google.gears.*, which is *the only* supported way to access Gears. 28 * 29 * Circumvent this file at your own risk! 30 * 31 * In the future, Gears may automatically define google.gears.* without this 32 * file. Gears may use these objects to transparently fix bugs and compatibility 33 * issues. Applications that use the code below will continue to work seamlessly 34 * when that happens. 35 */ 36 37 (function() { 38 // We are already defined. Hooray! 39 if (window.google && google.gears) { 40 return; 41 } 42 43 var factory = null; 44 45 // Firefox 46 if (typeof GearsFactory != 'undefined') { 47 factory = new GearsFactory(); 48 } else { 49 // IE 50 try { 51 factory = new ActiveXObject('Gears.Factory'); 52 // privateSetGlobalObject is only required and supported on WinCE. 53 if (factory.getBuildInfo().indexOf('ie_mobile') != -1) { 54 factory.privateSetGlobalObject(this); 55 } 56 } catch (e) { 57 // Safari 58 if ((typeof navigator.mimeTypes != 'undefined') 59 && navigator.mimeTypes["application/x-googlegears"]) { 60 factory = document.createElement("object"); 61 factory.style.display = "none"; 62 factory.width = 0; 63 factory.height = 0; 64 factory.type = "application/x-googlegears"; 65 document.documentElement.appendChild(factory); 66 } 67 } 68 } 69 70 // *Do not* define any objects if Gears is not installed. This mimics the 71 // behavior of Gears defining the objects in the future. 72 if (!factory) { 73 return; 74 } 75 76 // Now set up the objects, being careful not to overwrite anything. 77 // 78 // Note: In Internet Explorer for Windows Mobile, you can't add properties to 79 // the window object. However, global objects are automatically added as 80 // properties of the window object in all browsers. 81 if (!window.google) { 82 google = {}; 83 } 84 85 if (!google.gears) { 86 google.gears = {factory: factory}; 87 } 88 })(); -
lib/OpenLayers.js
old new 83 83 "OpenLayers/Tween.js", 84 84 "Rico/Corner.js", 85 85 "Rico/Color.js", 86 "Gears/gears_init.js", 86 87 "OpenLayers/Ajax.js", 87 88 "OpenLayers/Request.js", 88 89 "OpenLayers/Request/XMLHttpRequest.js", … … 184 185 "OpenLayers/Strategy.js", 185 186 "OpenLayers/Strategy/Fixed.js", 186 187 "OpenLayers/Protocol.js", 188 "OpenLayers/Protocol/SQL.js", 189 "OpenLayers/Protocol/SQL/Gears.js", 187 190 "OpenLayers/Layer/PointTrack.js", 188 191 "OpenLayers/Layer/GML.js", 189 192 "OpenLayers/Style.js", -
examples/protocol-gears.html
old new 1 <html xmlns="http://www.w3.org/1999/xhtml"> 2 <head> 3 <link rel="stylesheet" href="../theme/default/style.css" type="text/css" /> 4 <link rel="stylesheet" href="style.css" type="text/css" /> 5 <style type="text/css"> 6 .float-left { 7 float: left; 8 } 9 .clear-left { 10 clear: left; 11 } 12 </style> 13 <script src="../lib/OpenLayers.js"></script> 14 <script type="text/javascript"> 15 var map, vector, protocol, modify; 16 17 function init() { 18 // create Gears protocol 19 protocol = new OpenLayers.Protocol.SQL.Gears({ 20 databaseName: "db_name", 21 tableName: "table_name", 22 saveFeatureState: false 23 }); 24 25 if (!GearsIsSupported()) { 26 return; 27 } 28 29 map = new OpenLayers.Map("map"); 30 31 // create base layer 32 var layer = new OpenLayers.Layer.WMS("OpenLayers WMS", 33 "http://labs.metacarta.com/wms/vmap0", 34 {"layers": "basic"} 35 ); 36 map.addLayer(layer); 37 38 // create vector layer 39 vector = new OpenLayers.Layer.Vector("Vector", { 40 protocol: protocol, 41 strategies : [new OpenLayers.Strategy.Fixed()], 42 eventListeners: { 43 featuremodified: function(obj) { 44 if (obj.feature.state != OpenLayers.State.INSERT && 45 obj.feature.state != OpenLayers.State.DELETE) { 46 47 obj.feature.state = OpenLayers.State.UPDATE; 48 } 49 displayStatus(); 50 } 51 } 52 }); 53 map.addLayer(vector); 54 55 // create modify feature control 56 modify = new OpenLayers.Control.ModifyFeature(vector); 57 58 // create editing panel 59 var panel = new OpenLayers.Control.Panel({ 60 displayClass: "olControlEditingToolbar" 61 }); 62 63 var navigation = new OpenLayers.Control.Navigation({ 64 eventListeners: { 65 activate: function(obj) { 66 modify.activate(); 67 }, 68 deactivate: function(obj) { 69 modify.deactivate(); 70 } 71 } 72 }); 73 74 var editing = new OpenLayers.Control.DrawFeature( 75 vector, OpenLayers.Handler.Polygon, { 76 displayClass: "olControlDrawFeaturePolygon", 77 eventListeners: { 78 featureadded: function(obj) { 79 obj.feature.state = OpenLayers.State.INSERT; 80 displayStatus(); 81 } 82 } 83 }); 84 panel.addControls([navigation, editing]); 85 panel.defaultControl = navigation; 86 87 // add controls to the map 88 map.addControl(modify); 89 map.addControl(panel); 90 91 // center the map 92 map.setCenter(new OpenLayers.LonLat(5, 40), 5); 93 } 94 95 function displayResult(txt) { 96 if (window.resultDomElement === undefined) { 97 window.resultDomElement = OpenLayers.Util.getElement("last-result"); 98 } 99 resultDomElement.innerHTML = txt; 100 displayStatus(); 101 } 102 103 function displayStatus() { 104 if (window.statusDomElement === undefined) { 105 window.statusDomElement = OpenLayers.Util.getElement("status"); 106 } 107 108 var createCnt = 0; 109 var updateCnt = 0; 110 var deleteCnt = 0; 111 var i, len, state; 112 for (i = 0, len = vector.features.length; i < len; i++) { 113 state = vector.features[i].state; 114 if (state == OpenLayers.State.INSERT) { 115 createCnt++; 116 } else if (state == OpenLayers.State.UPDATE) { 117 updateCnt++; 118 } else if (state == OpenLayers.State.DELETE) { 119 deleteCnt++; 120 } 121 } 122 statusDomElement.innerHTML = createCnt + " features to create, " + 123 updateCnt + " features to update, " + 124 deleteCnt + " features to delete"; 125 } 126 127 function GearsIsSupported() { 128 if (!protocol.supported()) { 129 OpenLayers.Console.userError("You must install Gears prior to using this example"); 130 return false; 131 } 132 return true; 133 } 134 135 function featuresWithState(state) { 136 var list = []; 137 var i, len, feature; 138 for (i = 0, len = vector.features.length; i < len; i++) { 139 feature = vector.features[i]; 140 if (feature.state == state) { 141 list.push(feature); 142 } 143 } 144 return list; 145 } 146 147 function _sync() { 148 if (!GearsIsSupported()) { 149 return; 150 } 151 var resp = protocol.read(); 152 if (!resp.success()) { 153 OpenLayers.Console.error("reading from Gears DB failed"); 154 return; 155 } 156 vector.destroyFeatures(); 157 if (!resp.features || resp.features.length <= 0) { 158 displayResult("No features to read"); 159 return; 160 } 161 vector.addFeatures(resp.features); 162 displayResult("features successfully read"); 163 } 164 165 function _commit() { 166 if (!GearsIsSupported()) { 167 return; 168 } 169 var error = false; 170 function callback(resp) { 171 if (error) { 172 return; 173 } 174 if (!resp.success()) { 175 OpenLayers.Console.error("Commiting to Gears DB failed"); 176 error = true; 177 return; 178 } 179 modify.selectControl.unselectAll() 180 181 if (resp.reqFeatures) { 182 vector.destroyFeatures(resp.reqFeatures); 183 } 184 if (resp.features) { 185 vector.addFeatures(resp.features); 186 } 187 } 188 if (vector.features.length > 0) { 189 protocol.commit(vector.features, { 190 "create": { 191 callback: callback 192 }, 193 "update": { 194 callback: callback 195 }, 196 "delete": { 197 callback: callback 198 } 199 }); 200 if (!error) { 201 displayResult("features successfully committed"); 202 } 203 } else { 204 displayResult("no features to commit"); 205 } 206 } 207 208 function _delete() { 209 if (!GearsIsSupported()) { 210 return; 211 } 212 var feature = vector.selectedFeatures[0]; 213 if (feature) { 214 modify.selectControl.unselectAll() 215 feature.state = OpenLayers.State.DELETE; 216 displayStatus(); 217 } 218 } 219 </script> 220 </head> 221 <body onload="init()"> 222 <h1 id="title">Gears Protocol Example</h1> 223 224 <div id="tags"> 225 </div> 226 <p id="shortdesc"> 227 Shows the usage of the Gears protocol. 228 </p> 229 230 <div class="float-left"> 231 <div id="map" class="smallmap"></div> 232 </div> 233 234 <div> 235 <a href="javascript:_sync()">Sync</a> 236 <p>The Sync link destroys the features currently in the layer, reads 237 features from the Gears database, and adds them to the layer. 238 Uncommitted features will be lost.</p> 239 240 <a href="javascript:_commit()">Commit</a> 241 <p>The Commit link commits to the Gears database the features that are 242 marked as INSERT, UPDATE or DELETE.</p> 243 244 <a href="javascript:_delete()">Delete</a> 245 <p>The Delete link marks the selected feature as DELETE. To select a feature 246 click choose the navigation control in the editing toolbar.</p> 247 </div> 248 249 <div style="margin-top: 30px"> 250 <p>Status: <span id="status"></span></p> 251 <p>Result: <span id="last-result"></span></p> 252 </div> 253 254 <div class="clear-left" id="docs"> 255 <p>This example demonstrates the usage of OpenLayers Gears protocol to 256 read/create/update/delete features from/to the Gears database. 257 <a href="http://gears.google.com/">Gears</a> must obviously be installed 258 in your browser for this example to work.</p> 259 </div> 260 </body> 261 </html>
