Bienvenue sur PostGIS.fr

Bienvenue sur PostGIS.fr , le site de la communauté des utilisateurs francophones de PostGIS.

PostGIS ajoute le support d'objets géographique à la base de données PostgreSQL. En effet, PostGIS "spatialise" le serverur PostgreSQL, ce qui permet de l'utiliser comme une base de données SIG.

Maintenu à jour, en fonction de nos disponibilités et des diverses sorties des outils que nous testons, nous vous proposons l'ensemble de nos travaux publiés en langue française.

source: trunk/workshop-routing-foss4g/web/OpenLayers/lib/OpenLayers/Protocol/SQL/Gears.js @ 76

Revision 76, 16.4 KB checked in by djay, 12 years ago (diff)

Ajout du répertoire web

  • Property svn:executable set to *
Line 
1/* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for
2 * full list of contributors). Published under the Clear BSD license. 
3 * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
4 * full text of the license. */
5
6/**
7 * @requires Gears/gears_init.js
8 * @requires OpenLayers/Protocol/SQL.js
9 * @requires OpenLayers/Format/JSON.js
10 * @requires OpenLayers/Format/WKT.js
11 */
12
13/**
14 * Class: OpenLayers.Protocol.SQL.Gears
15 * This Protocol stores feature in the browser via the Gears Database module
16 * <http://code.google.com/apis/gears/api_database.html>.
17 *
18 * The main advantage is that all the read, create, update and delete operations
19 * can be done offline.
20 *
21 * Inherits from:
22 *  - <OpenLayers.Protocol.SQL>
23 */
24OpenLayers.Protocol.SQL.Gears = OpenLayers.Class(OpenLayers.Protocol.SQL, {
25
26    /**
27     * Property: FID_PREFIX
28     * {String}
29     */
30    FID_PREFIX: '__gears_fid__',
31
32    /**
33     * Property: NULL_GEOMETRY
34     * {String}
35     */
36    NULL_GEOMETRY: '__gears_null_geometry__',
37
38    /**
39     * Property: NULL_FEATURE_STATE
40     * {String}
41     */
42    NULL_FEATURE_STATE: '__gears_null_feature_state__',
43
44    /**
45     * Property: jsonParser
46     * {<OpenLayers.Format.JSON>}
47     */
48    jsonParser: null,
49
50    /**
51     * Property: wktParser
52     * {<OpenLayers.Format.WKT>}
53     */
54    wktParser: null,
55
56    /**
57     * Property: fidRegExp
58     * {RegExp} Regular expression to know whether a feature was
59     *      created in offline mode.
60     */
61    fidRegExp: null,
62
63    /**
64     * Property: saveFeatureState
65     * {Boolean} Whether to save the feature state (<OpenLayers.State>)
66     *      into the database, defaults to true.
67     */   
68    saveFeatureState: true,
69
70    /**
71     * Property: typeOfFid
72     * {String} The type of the feature identifier, either "number" or
73     *      "string", defaults to "string".
74     */
75    typeOfFid: "string",
76
77    /**
78     * Property: db
79     * {GearsDatabase}
80     */
81    db: null,
82
83    /**
84     * Constructor: OpenLayers.Protocol.SQL.Gears
85     */
86    initialize: function(options) {
87        if (!this.supported()) {
88            return;
89        }
90        OpenLayers.Protocol.SQL.prototype.initialize.apply(this, [options]);
91        this.jsonParser = new OpenLayers.Format.JSON();
92        this.wktParser = new OpenLayers.Format.WKT();
93
94        this.fidRegExp = new RegExp('^' + this.FID_PREFIX);
95        this.initializeDatabase();
96
97       
98    },
99
100    /**
101     * Method: initializeDatabase
102     */
103    initializeDatabase: function() {
104        this.db = google.gears.factory.create('beta.database');
105        this.db.open(this.databaseName);
106        this.db.execute(
107            "CREATE TABLE IF NOT EXISTS " + this.tableName +
108            " (fid TEXT UNIQUE, geometry TEXT, properties TEXT," +
109            "  state TEXT)");
110   },
111
112    /**
113     * APIMethod: destroy
114     * Clean up the protocol.
115     */
116    destroy: function() {
117        this.db.close();
118        this.db = null;
119
120        this.jsonParser = null;
121        this.wktParser = null;
122
123        OpenLayers.Protocol.SQL.prototype.destroy.apply(this);
124    },
125
126    /**
127     * APIMethod: supported
128     * Determine whether a browser supports Gears
129     *
130     * Returns:
131     * {Boolean} The browser supports Gears
132     */
133    supported: function() {
134        return !!(window.google && google.gears);
135    },
136
137    /**
138     * APIMethod: read
139     * Read all features from the database and return a
140     * <OpenLayers.Protocol.Response> instance. If the options parameter
141     * contains a callback attribute, the function is called with the response
142     * as a parameter.
143     *
144     * Parameters:
145     * options - {Object} Optional object for configuring the request; it
146     *      can have the {Boolean} property "noFeatureStateReset" which
147     *      specifies if the state of features read from the Gears
148     *      database must be reset to null, if "noFeatureStateReset"
149     *      is undefined or false then each feature's state is reset
150     *      to null, if "noFeatureStateReset" is true the feature state
151     *      is preserved.
152     *
153     * Returns:
154     * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
155     *      object.
156     */
157    read: function(options) {
158        OpenLayers.Protocol.prototype.read.apply(this, arguments);
159        options = OpenLayers.Util.applyDefaults(options, this.options);
160
161        var feature, features = [];
162        var rs = this.db.execute("SELECT * FROM " + this.tableName);
163        while (rs.isValidRow()) {
164            feature = this.unfreezeFeature(rs);
165            if (this.evaluateFilter(feature, options.filter)) {
166                if (!options.noFeatureStateReset) {
167                    feature.state = null;
168                }
169                features.push(feature);
170            }
171            rs.next();
172        }
173        rs.close();
174
175        var resp = new OpenLayers.Protocol.Response({
176            code: OpenLayers.Protocol.Response.SUCCESS,
177            requestType: "read",
178            features: features
179        });
180
181        if (options && options.callback) {
182            options.callback.call(options.scope, resp);
183        }
184
185        return resp;
186    },
187
188    /**
189     * Method: unfreezeFeature
190     *
191     * Parameters:
192     * row - {ResultSet}
193     *
194     * Returns:
195     * {<OpenLayers.Feature.Vector>}
196     */
197    unfreezeFeature: function(row) {
198        var feature;
199        var wkt = row.fieldByName('geometry');
200        if (wkt == this.NULL_GEOMETRY) {
201            feature = new OpenLayers.Feature.Vector();
202        } else {
203            feature = this.wktParser.read(wkt);
204        }
205
206        feature.attributes = this.jsonParser.read(
207            row.fieldByName('properties'));
208
209        feature.fid = this.extractFidFromField(row.fieldByName('fid'));
210
211        var state = row.fieldByName('state');
212        if (state == this.NULL_FEATURE_STATE) {
213            state = null;
214        }
215        feature.state = state;
216
217        return feature;
218    },
219
220    /**
221     * Method: extractFidFromField
222     *
223     * Parameters:
224     * field - {String}
225     *
226     * Returns
227     * {String} or {Number} The fid.
228     */
229    extractFidFromField: function(field) {
230        if (!field.match(this.fidRegExp) && this.typeOfFid == "number") {
231            field = parseFloat(field);
232        }
233        return field;
234    },
235
236    /**
237     * APIMethod: create
238     * Create new features into the database.
239     *
240     * Parameters:
241     * features - {Array({<OpenLayers.Feature.Vector>})} or
242     *            {<OpenLayers.Feature.Vector>} The features to create in
243     *            the database.
244     * options - {Object} Optional object for configuring the request.
245     *
246     * Returns:
247     *  {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
248     *          object.
249     */
250    create: function(features, options) {
251        options = OpenLayers.Util.applyDefaults(options, this.options);
252
253        var resp = this.createOrUpdate(features);
254        resp.requestType = "create";
255
256        if (options && options.callback) {
257            options.callback.call(options.scope, resp);
258        }
259
260        return resp;
261    },
262
263    /**
264     * APIMethod: update
265     * Construct a request updating modified feature.
266     *
267     * Parameters:
268     * features - {Array({<OpenLayers.Feature.Vector>})} or
269     *            {<OpenLayers.Feature.Vector>} The features to update in
270     *            the database.
271     * options - {Object} Optional object for configuring the request.
272     *
273     * Returns:
274     *  {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
275     *          object.
276     */
277    update: function(features, options) {
278        options = OpenLayers.Util.applyDefaults(options, this.options);
279
280        var resp = this.createOrUpdate(features);
281        resp.requestType = "update";
282
283        if (options && options.callback) {
284            options.callback.call(options.scope, resp);
285        }
286
287        return resp;
288    },
289
290    /**
291     * Method: createOrUpdate
292     * Construct a request for updating or creating features in the
293     * database.
294     *
295     * Parameters:
296     * features - {Array({<OpenLayers.Feature.Vector>})} or
297     *      {<OpenLayers.Feature.Vector>} The feature to create or update
298     *      in the database.
299     *
300     * Returns:
301     *  {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
302     *          object.
303     */
304    createOrUpdate: function(features) {
305        if (!(features instanceof Array)) {
306            features = [features];
307        }
308
309        var i, len = features.length, feature;
310        var insertedFeatures = new Array(len);
311 
312        for (i = 0; i < len; i++) {
313            feature = features[i];
314            var params = this.freezeFeature(feature);
315            this.db.execute(
316                "REPLACE INTO " + this.tableName + 
317                " (fid, geometry, properties, state)" + 
318                " VALUES (?, ?, ?, ?)",
319                params);
320
321            var clone = feature.clone();
322            clone.fid = this.extractFidFromField(params[0]);
323            insertedFeatures[i] = clone;
324        }
325
326        return new OpenLayers.Protocol.Response({
327            code: OpenLayers.Protocol.Response.SUCCESS,
328            features: insertedFeatures,
329            reqFeatures: features
330        });
331    },
332
333    /**
334     * Method: freezeFeature
335     *
336     * Parameters:
337     * feature - {<OpenLayers.Feature.Vector>}
338     * state - {String} The feature state to store in the database.
339     *
340     * Returns:
341     * {Array}
342     */
343    freezeFeature: function(feature) {
344        // 2 notes:
345        // - fid might not be a string
346        // - getFeatureStateForFreeze needs the feature fid to it's stored
347        //   in the feature here
348        feature.fid = feature.fid != null ?
349            "" + feature.fid : OpenLayers.Util.createUniqueID(this.FID_PREFIX);
350
351        var geometry = feature.geometry != null ?
352            feature.geometry.toString() : this.NULL_GEOMETRY;
353
354        var properties = this.jsonParser.write(feature.attributes);
355
356        var state = this.getFeatureStateForFreeze(feature);
357
358        return [feature.fid, geometry, properties, state];
359    },
360
361    /**
362     * Method: getFeatureStateForFreeze
363     * Get the state of the feature to store into the database.
364     *
365     * Parameters:
366     * feature - {<OpenLayers.Feature.Vector>} The feature.
367     *
368     * Returns
369     * {String} The state
370     */
371    getFeatureStateForFreeze: function(feature) {
372        var state;
373        if (!this.saveFeatureState) {
374            state = this.NULL_FEATURE_STATE;
375        } else if (this.createdOffline(feature)) {
376            // if the feature was created in offline mode, its
377            // state must remain INSERT
378            state = OpenLayers.State.INSERT;
379        } else {
380            state = feature.state;
381        }
382        return state;
383    },
384
385    /**
386     * APIMethod: delete
387     * Delete features from the database.
388     *
389     * Parameters:
390     * features - {Array({<OpenLayers.Feature.Vector>})} or
391     *            {<OpenLayers.Feature.Vector>}
392     * options - {Object} Optional object for configuring the request.
393     *       This object is modified and should not be reused.
394     *
395     * Returns:
396     *  {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
397     *          object.
398     */
399    "delete": function(features, options) {
400        if (!(features instanceof Array)) {
401            features = [features];
402        }
403
404        options = OpenLayers.Util.applyDefaults(options, this.options);
405
406        var i, len, feature;
407        for (i = 0, len = features.length; i < len; i++) {
408            feature = features[i];
409
410            // if saveFeatureState is set to true and if the feature wasn't created
411            // in offline mode we don't delete it in the database but just update
412            // it state column
413            if (this.saveFeatureState && !this.createdOffline(feature)) {
414                var toDelete = feature.clone();
415                toDelete.fid = feature.fid;
416                if (toDelete.geometry) {
417                    toDelete.geometry.destroy();
418                    toDelete.geometry = null;
419                }
420                toDelete.state = feature.state;
421                this.createOrUpdate(toDelete);
422            } else {
423                this.db.execute(
424                    "DELETE FROM " + this.tableName +
425                    " WHERE fid = ?", [feature.fid]);
426            }
427        }
428
429        var resp = new OpenLayers.Protocol.Response({
430            code: OpenLayers.Protocol.Response.SUCCESS,
431            requestType: "delete",
432            reqFeatures: features
433        });
434
435        if (options && options.callback) {
436            options.callback.call(options.scope, resp);
437        }
438
439        return resp;
440    },
441
442    /**
443     * Method: createdOffline
444     * Returns true if the feature had a feature id when it was created in
445     *      the Gears database, false otherwise; this is determined by
446     *      checking the form of the feature's fid value.
447     *
448     * Parameters:
449     * feature - {<OpenLayers.Feature.Vector>}
450     *
451     * Returns:
452     * {Boolean}
453     */
454    createdOffline: function(feature) {
455        return (typeof feature.fid == "string" &&
456                !!(feature.fid.match(this.fidRegExp)));
457    },
458
459    /**
460     * APIMethod: commit
461     * Go over the features and for each take action
462     * based on the feature state. Possible actions are create,
463     * update and delete.
464     *
465     * Parameters:
466     * features - {Array({<OpenLayers.Feature.Vector>})}
467     * options - {Object} Object whose possible keys are "create", "update",
468     *      "delete", "callback" and "scope", the values referenced by the
469     *      first three are objects as passed to the "create", "update", and
470     *      "delete" methods, the value referenced by the "callback" key is
471     *      a function which is called when the commit operation is complete
472     *      using the scope referenced by the "scope" key.
473     *
474     * Returns:
475     * {Array({<OpenLayers.Protocol.Response>})} An array of
476     *       <OpenLayers.Protocol.Response> objects, one per request made
477     *       to the database.
478     */
479    commit: function(features, options) {
480        var opt, resp = [], nRequests = 0, nResponses = 0;
481
482        function callback(resp) {
483            if (++nResponses < nRequests) {
484                resp.last = false;
485            }
486            this.callUserCallback(options, resp);
487        }
488
489        var feature, toCreate = [], toUpdate = [], toDelete = [];
490        for (var i = features.length - 1; i >= 0; i--) {
491            feature = features[i];
492            switch (feature.state) {
493            case OpenLayers.State.INSERT:
494                toCreate.push(feature);
495                break;
496            case OpenLayers.State.UPDATE:
497                toUpdate.push(feature);
498                break;
499            case OpenLayers.State.DELETE:
500                toDelete.push(feature);
501                break;
502            }
503        }
504        if (toCreate.length > 0) {
505            nRequests++;
506            opt = OpenLayers.Util.applyDefaults(
507                {"callback": callback, "scope": this},
508                options.create
509            );
510            resp.push(this.create(toCreate, opt));
511        }
512        if (toUpdate.length > 0) {
513            nRequests++;
514            opt = OpenLayers.Util.applyDefaults(
515                {"callback": callback, "scope": this},
516                options.update
517            );
518            resp.push(this.update(toUpdate, opt));
519        }
520        if (toDelete.length > 0) {
521            nRequests++;
522            opt = OpenLayers.Util.applyDefaults(
523                {"callback": callback, "scope": this},
524                options["delete"]
525            );
526            resp.push(this["delete"](toDelete, opt));
527        }
528
529        return resp;
530    },
531
532    /**
533     * Method: clear
534     * Removes all rows of the table.
535     */
536    clear: function() {
537        this.db.execute("DELETE FROM " + this.tableName);
538    },
539
540    /**
541     * Method: callUserCallback
542     * This method is called from within commit each time a request is made
543     * to the database, it is responsible for calling the user-supplied
544     * callbacks.
545     *
546     * Parameters:
547     * options - {Object} The map of options passed to the commit call.
548     * resp - {<OpenLayers.Protocol.Response>}
549     */
550    callUserCallback: function(options, resp) {
551        var opt = options[resp.requestType];
552        if (opt && opt.callback) {
553            opt.callback.call(opt.scope, resp);
554        }
555        if (resp.last && options.callback) {
556            options.callback.call(options.scope);
557        }
558    },
559
560    CLASS_NAME: "OpenLayers.Protocol.SQL.Gears"
561});
Note: See TracBrowser for help on using the repository browser.