text: /*
   * Copyright (C) 2007  Camptocamp
   *
   * This file is part of MapFish Client
   *
   * MapFish Client is free software: you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   *
   * MapFish Client is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with MapFish Client.  If not, see <http://www.gnu.org/licenses/>.
   */
  
  /*
   * @requires OpenLayers/Util.js
   * @requires OpenLayers/Protocol.js
   * @requires core/Protocol.js
   */
  
  /**
   * Class: mapfish.Protocol.TriggerEventDecorator
   * Decorator class responsible to trigger events when requests are
   * sent and received.
   *
   * Inherits from:
   * - <OpenLayers.Protocol>
   */
  
  mapfish.Protocol.TriggerEventDecorator = OpenLayers.Class(OpenLayers.Protocol, {
  
      /**
       * APIProperty: protocol
       * {<OpenLayers.Protocol>} The decorated protocol.
       */
      protocol: null,
  
      /**
       * Property: events
       * {<OpenLayers.Events>}
       */
      events: null,
  
      /**
       * Constant: EVENT_TYPES
       * {Array(String)} Supported event types. Register a listener
       *     for a particular event with the following syntax:
       *
       * (start code)
       * protocol.events.register(type, obj, listener);
       * (end)
       *
       * Listeners will be called with a reference to an event object.
       *
       * Supported events:
       * - *crudtriggered* Triggered when either "create", "read", "update"
       *     or "delete" is called, listeners will receive an object with
       *     a type property referencing either the string "create",
       *     "read", "update", or "delete" depending on what type of
       *     CRUD operation is actually triggered.
       * - *crudfinished* Triggered when either "create", "read", "update"
       *     or "delete" is finished, listeners will receive an
       *     <OpenLayers.Protocol.Response> object.
       * - *committriggered* Triggered when a commit operation is triggered.
       * - *commitfinished* Triggered when a commit operation is finished.
       * - *clear* Triggered when the clear API method is called.
       */
      EVENT_TYPES: ["crudtriggered", "crudfinished",
                    "committriggered", "commitfinished",
                    "clear"],
  
      /**
       * Constructor: mapfish.Protocol.TriggerEventDecorator
       *
       * Parameters:
       * options - {Object} Optional parameters to set in the protocol.
       *
       * Returns:
       * {<mapfish.Protocol.TriggerEventDecorator>}
       */
      initialize: function(options) {
          OpenLayers.Protocol.prototype.initialize.call(this, options);
          this.events = new OpenLayers.Events(this, null, this.EVENT_TYPES);
          if (this.eventListeners instanceof Object) {
              this.events.on(this.eventListeners);
          }
      },
  
      /**
       * APIMethod: read
       * Construct a request for reading new features.
       *
       * Parameters:
       * options - {Object} Optional object for configuring the request.
       *
       * Returns:
       * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
       * object, the same object will be passed to the callback function passed
       * if one exists in the options object.
       */
      read: function(options) {
          var newOptions = OpenLayers.Util.applyDefaults({
              callback: this.createCallback(this.handleCRUD, options),
              scope: null
          }, options);
          this.events.triggerEvent("crudtriggered", {type: "read"});
          return this.protocol.read(newOptions);
      },
      
      
      /**
       * APIMethod: create
       * Construct a request for writing newly created features.
       *
       * Parameters:
       * features - {Array({<OpenLayers.Feature.Vector>})} or
       *            {<OpenLayers.Feature.Vector>}
       * options - {Object} Optional object for configuring the request.
       *
       * Returns:
       * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
       * object, the same object will be passed to the callback function passed
       * if one exists in the options object.
       */
      create: function(features, options) {
          var newOptions = OpenLayers.Util.applyDefaults({
              callback: this.createCallback(this.handleCRUD, options),
              scope: null
          }, options);
          this.events.triggerEvent("crudtriggered", {type: "create"});
          return this.protocol.create(features, newOptions);
      },
      
      /**
       * APIMethod: update
       * Construct a request updating modified features.
       *
       * Parameters:
       * features - {Array({<OpenLayers.Feature.Vector>})} or
       *            {<OpenLayers.Feature.Vector>}
       * options - {Object} Optional object for configuring the request.
       *
       * Returns:
       * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
       * object, the same object will be passed to the callback function passed
       * if one exists in the options object.
       */
      update: function(features, options) {
          var newOptions = OpenLayers.Util.applyDefaults({
              callback: this.createCallback(this.handleCRUD, options),
              scope: null
          }, options);
          this.events.triggerEvent("crudtriggered", {type: "update"});
          return this.protocol.update(features, newOptions);
      },
      
      /**
       * APIMethod: delete
       * Construct a request deleting a removed feature.
       *
       * Parameters:
       * feature - {<OpenLayers.Feature.Vector>}
       * options - {Object} Optional object for configuring the request.
       *
       * Returns:
       * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
       * object, the same object will be passed to the callback function passed
       * if one exists in the options object.
       */
      "delete": function(feature, options) {
          var newOptions = OpenLayers.Util.applyDefaults({
              callback: this.createCallback(this.handleCRUD, options),
              scope: null
          }, options);
          this.events.triggerEvent("crudtriggered", {type: "delete"});
          return this.protocol["delete"](feature, newOptions);
      },
  
      /**
       * APIMethod: commit
       * Go over the features and for each take action
       * based on the feature state. Possible actions are create,
       * update and delete.
       *
       * Parameters:
       * features - {Array({<OpenLayers.Feature.Vector>})}
       * options - {Object} Object whose possible keys are "create", "update",
       *      "delete", "callback" and "scope", the values referenced by the
       *      first three are objects as passed to the "create", "update", and
       *      "delete" methods, the value referenced by the "callback" key is
       *      a function which is called when the commit operation is complete
       *      using the scope referenced by the "scope" key.
       *
       * Returns:
       * {Array({<OpenLayers.Protocol.Response>})} An array of
       * <OpenLayers.Protocol.Response> objects.
       */
      commit: function(features, options) {
          var newOptions = OpenLayers.Util.applyDefaults({
              callback: this.createCallback(this.handleCommit, options),
              scope: null
          }, options);
          this.events.triggerEvent("committriggered");
          return this.protocol.commit(features, newOptions);
      },
  
      /**
       * Method: abort
       * Abort an ongoing request.
       *
       * Parameters:
       * response - {<OpenLayers.Protocol.Response>}
       */
      abort: function(response) {
          this.protocol.abort(response);
      },
  
      /**
       * Method: createCallback
       * Returns a function that applies the given public method with the
       * options argument.
       *
       * Parameters:
       * method - {Function} The method to be applied by the callback.
       * options - {Object} Options sent to the protocol method (read, create,
       *     update, or delete).
       */
      createCallback: function(method, options) {
          return OpenLayers.Function.bind(method, this, options);
      },
  
      /**
       * Method: handleCRUD
       * Method used to handle "create", "read", "update", and "delete"
       * operations.
       *
       * Parameters:
       * options - {Object} Options sent to the protocol method (read, create,
       *     update, or delete).
       * response - {<OpenLayers.Protocol.Response>} Response object received
       *     from the underlying protocol.
       */
      handleCRUD: function(options, response) {
          if (options && options.callback) {
              options.callback.call(options.scope, response);
          }
          this.events.triggerEvent("crudfinished", response);
      },
  
      /**
       * Method: handleCommit
       * Method used to handle "commit" operations.
       *
       * Parameters:
       * options -  {Object} Options sent to the protocol commit method.
       */
      handleCommit: function(options) {
          if (options.callback) {
              options.callback.call(options.scope);
          }
          this.events.triggerEvent("commitfinished");
      },
  
      /**
       * APIMethod: clear
       *      Clear all the previous results.
       */
      clear: function() {
          this.events.triggerEvent("clear");
      },
  
      CLASS_NAME: "mapfish.Protocol.TriggerEventDecorator"
  });
  