text: /**
   * Copyright (c) 2008-2012 The Open Source Geospatial Foundation
   *
   * Published under the BSD license.
   * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
   * of the license.
   */
  
  /**
   * @include GeoExt/data/AttributeReader.js
   */
  
  /** api: (define)
   *  module = GeoExt.data
   *  class = AttributeStore
   *  base_link = `Ext.data.Store <http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Store>`_
   */
  Ext.namespace("GeoExt.data");
  
  /**
   * Function: GeoExt.data.AttributeStoreMixin
   *
   * This function generates a mixin object to be used when extending an Ext.data.Store
   * to create an attribute store.
   *
   * (start code)
   * var AttrStore = Ext.extend(Ext.data.Store, GeoExt.data.AttributeStoreMixin);
   * var store = new AttrStore();
   * (end)
   *
   * For convenience, a GeoExt.data.AttributeStore class is available as a
   * shortcut to the Ext.extend sequence in the above code snippet. The above
   * is equivalent to:
   * (start code)
   * var store = new GeoExt.data.AttributeStore();
   * (end)
   */
  GeoExt.data.AttributeStoreMixin = function() {
      return {
          /** private */
          constructor: function(c) {
              c = c || {};
              arguments.callee.superclass.constructor.call(
                  this,
                  Ext.apply(c, {
                      proxy: c.proxy || (!c.data ?
                          new Ext.data.HttpProxy({url: c.url, disableCaching: false, method: "GET"}) :
                          undefined
                      ),
                      reader: new GeoExt.data.AttributeReader(
                          c, c.fields || ["name", "type", "restriction", {
                              name: "nillable", type: "boolean"
                          }, "annotation"]
                      )
                  })
              );
              if(this.feature) {
                  this.bind();
              }
          },
  
          /** private: method[bind]
           */
          bind: function() {
              this.on({
                  "update": this.onUpdate,
                  "load": this.onLoad,
                  "add": this.onAdd,
                  scope: this
              });
              var records = [];
              this.each(function(record) {
                  records.push(record);
              });
              this.updateFeature(records);
          },
  
          /** private: method[onUpdate]
           *  :param store: ``Ext.data.Store``
           *  :param record: ``Ext.data.Record``
           *  :param operation: ``String``
           *
           *  Handler for store update event.
           */
          onUpdate: function(store, record, operation) {
              this.updateFeature([record]);
          },
  
          /** private: method[onLoad]
           *  :param store: ``Ext.data.Store``
           *  :param records: ``Array(Ext.data.Record)``
           *  :param options: ``Object``
           *
           *  Handler for store load event
           */
          onLoad: function(store, records, options) {
              // if options.add is true an "add" event was already
              // triggered, and onAdd already did the work of
              // adding the features to the layer.
              if(!options || options.add !== true) {
                  this.updateFeature(records);
              }
          },
  
          /** private: method[onAdd]
           *  :param store: ``Ext.data.Store``
           *  :param records: ``Array(Ext.data.Record)``
           *  :param index: ``Number``
           *
           *  Handler for store add event
           */
          onAdd: function(store, records, index) {
              this.updateFeature(records);
          },
  
          /** private: method[updateFeature]
           *  :param records: ``Array(Ext.data.Record)``
           *
           *  Update feature from records.
           */
          updateFeature: function(records) {
              var feature = this.feature, layer = feature.layer;
              var i, len, record, name, value, oldValue, dirty;
              for (i=0,len=records.length; i<len; i++) {
                  record = records[i];
                  name = record.get("name");
                  value = record.get("value");
                  oldValue = feature.attributes[name];
                  if (oldValue !== value) {
                      dirty = true;
                  }
              }
              if (dirty && layer && layer.events &&
                          layer.events.triggerEvent("beforefeaturemodified",
                              {feature: feature}) !== false) {
                  for (i=0,len=records.length; i<len; i++) {
                      record = records[i];
                      name = record.get("name");
                      value = record.get("value");
                      if (record.get("type") == 'xsd:date' && value instanceof Date) {
                          value = value.format('Y-m-d');
                      }
                      feature.attributes[name] = value;
                  }
                  layer.events.triggerEvent(
                      "featuremodified", {feature: feature});
                  layer.drawFeature(feature);
              }
          }
  
      };
  };
  
  /** api: constructor
   *  .. class:: AttributeStore(config)
   *
   *      Small helper class to make creating stores for remotely-loaded attributes
   *      data easier. AttributeStore is pre-configured with a built-in
   *      ``Ext.data.HttpProxy`` and :class:`GeoExt.data.AttributeReader`.  The
   *      HttpProxy is configured to allow caching (disableCaching: false) and
   *      uses GET. If you require some other proxy/reader combination then you'll
   *      have to configure this with your own proxy or create a basic
   *      ``Ext.data.Store`` and configure as needed.
   */
  
  /** api: config[format]
   *  ``OpenLayers.Format``
   *  A parser for transforming the XHR response into an array of objects
   *  representing attributes.  Defaults to an
   *  ``OpenLayers.Format.WFSDescribeFeatureType`` parser.
   */
  
  /** api: config[fields]
   *  ``Array or Function``
   *  Either an array of field definition objects as passed to
   *  ``Ext.data.Record.create``, or a record constructor created using
   *  ``Ext.data.Record.create``.  Defaults to ``["name", "type", "restriction"]``.
   */
  
  /** api: config[feature]
   *  ``OpenLayers.Feature.Vector``
   *  A vector feature. If provided, and if the reader is a
   *  :class:`GeoExt.data.AttributeReader` (the default), then records
   *  of this store will include a field named "value" referencing the
   *  corresponding attribute value in the feature. And if the "value"
   *  field of a record is updated the update will propagate to the
   *  corresponding feature attribute. Optional.
   */
  GeoExt.data.AttributeStore = Ext.extend(
      Ext.data.Store,
      GeoExt.data.AttributeStoreMixin()
  );
  