DataReader.js
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:10k
源码类别:

JavaScript

开发平台:

JavaScript

  1. /*!  * Ext JS Library 3.1.0  * Copyright(c) 2006-2009 Ext JS, LLC  * licensing@extjs.com  * http://www.extjs.com/license  */ /**
  2.  * @class Ext.data.DataReader
  3.  * Abstract base class for reading structured data from a data source and converting
  4.  * it into an object containing {@link Ext.data.Record} objects and metadata for use
  5.  * by an {@link Ext.data.Store}.  This class is intended to be extended and should not
  6.  * be created directly. For existing implementations, see {@link Ext.data.ArrayReader},
  7.  * {@link Ext.data.JsonReader} and {@link Ext.data.XmlReader}.
  8.  * @constructor Create a new DataReader
  9.  * @param {Object} meta Metadata configuration options (implementation-specific).
  10.  * @param {Array/Object} recordType
  11.  * <p>Either an Array of {@link Ext.data.Field Field} definition objects (which
  12.  * will be passed to {@link Ext.data.Record#create}, or a {@link Ext.data.Record Record}
  13.  * constructor created using {@link Ext.data.Record#create}.</p>
  14.  */
  15. Ext.data.DataReader = function(meta, recordType){
  16.     /**
  17.      * This DataReader's configured metadata as passed to the constructor.
  18.      * @type Mixed
  19.      * @property meta
  20.      */
  21.     this.meta = meta;
  22.     /**
  23.      * @cfg {Array/Object} fields
  24.      * <p>Either an Array of {@link Ext.data.Field Field} definition objects (which
  25.      * will be passed to {@link Ext.data.Record#create}, or a {@link Ext.data.Record Record}
  26.      * constructor created from {@link Ext.data.Record#create}.</p>
  27.      */
  28.     this.recordType = Ext.isArray(recordType) ?
  29.         Ext.data.Record.create(recordType) : recordType;
  30.     // if recordType defined make sure extraction functions are defined
  31.     if (this.recordType){
  32.         this.buildExtractors();
  33.     } };
  34. Ext.data.DataReader.prototype = {
  35.     /**
  36.      * @cfg {String} messageProperty [undefined] Optional name of a property within a server-response that represents a user-feedback message.
  37.      */
  38.     /**
  39.      * Abstract method created in extension's buildExtractors impl.
  40.      */
  41.     getTotal: Ext.emptyFn,
  42.     /**
  43.      * Abstract method created in extension's buildExtractors impl.
  44.      */
  45.     getRoot: Ext.emptyFn,
  46.     /**
  47.      * Abstract method created in extension's buildExtractors impl.
  48.      */
  49.     getMessage: Ext.emptyFn,
  50.     /**
  51.      * Abstract method created in extension's buildExtractors impl.
  52.      */
  53.     getSuccess: Ext.emptyFn,
  54.     /**
  55.      * Abstract method created in extension's buildExtractors impl.
  56.      */
  57.     getId: Ext.emptyFn,
  58.     /**
  59.      * Abstract method, overridden in DataReader extensions such as {@link Ext.data.JsonReader} and {@link Ext.data.XmlReader}
  60.      */
  61.     buildExtractors : Ext.emptyFn,
  62.     /**
  63.      * Abstract method overridden in DataReader extensions such as {@link Ext.data.JsonReader} and {@link Ext.data.XmlReader}
  64.      */
  65.     extractData : Ext.emptyFn,
  66.     /**
  67.      * Abstract method overridden in DataReader extensions such as {@link Ext.data.JsonReader} and {@link Ext.data.XmlReader}
  68.      */
  69.     extractValues : Ext.emptyFn,
  70.     /**
  71.      * Used for un-phantoming a record after a successful database insert.  Sets the records pk along with new data from server.
  72.      * You <b>must</b> return at least the database pk using the idProperty defined in your DataReader configuration.  The incoming
  73.      * data from server will be merged with the data in the local record.
  74.      * In addition, you <b>must</b> return record-data from the server in the same order received.
  75.      * Will perform a commit as well, un-marking dirty-fields.  Store's "update" event will be suppressed.
  76.      * @param {Record/Record[]} record The phantom record to be realized.
  77.      * @param {Object/Object[]} data The new record data to apply.  Must include the primary-key from database defined in idProperty field.
  78.      */
  79.     realize: function(rs, data){
  80.         if (Ext.isArray(rs)) {
  81.             for (var i = rs.length - 1; i >= 0; i--) {
  82.                 // recurse
  83.                 if (Ext.isArray(data)) {
  84.                     this.realize(rs.splice(i,1).shift(), data.splice(i,1).shift());
  85.                 }
  86.                 else {
  87.                     // weird...rs is an array but data isn't??  recurse but just send in the whole invalid data object.
  88.                     // the else clause below will detect !this.isData and throw exception.
  89.                     this.realize(rs.splice(i,1).shift(), data);
  90.                 }
  91.             }
  92.         }
  93.         else {
  94.             // If rs is NOT an array but data IS, see if data contains just 1 record.  If so extract it and carry on.
  95.             if (Ext.isArray(data) && data.length == 1) {
  96.                 data = data.shift();
  97.             }
  98.             if (!this.isData(data)) {
  99.                 // TODO: Let exception-handler choose to commit or not rather than blindly rs.commit() here.
  100.                 //rs.commit();
  101.                 throw new Ext.data.DataReader.Error('realize', rs);
  102.             }
  103.             rs.phantom = false; // <-- That's what it's all about
  104.             rs._phid = rs.id;  // <-- copy phantom-id -> _phid, so we can remap in Store#onCreateRecords
  105.             rs.id = this.getId(data);
  106.             rs.fields.each(function(f) {
  107.                 if (data[f.name] !== f.defaultValue) {
  108.                     rs.data[f.name] = data[f.name];
  109.                 }
  110.             });
  111.             rs.commit();
  112.         }
  113.     },
  114.     /**
  115.      * Used for updating a non-phantom or "real" record's data with fresh data from server after remote-save.
  116.      * If returning data from multiple-records after a batch-update, you <b>must</b> return record-data from the server in
  117.      * the same order received.  Will perform a commit as well, un-marking dirty-fields.  Store's "update" event will be
  118.      * suppressed as the record receives fresh new data-hash
  119.      * @param {Record/Record[]} rs
  120.      * @param {Object/Object[]} data
  121.      */
  122.     update : function(rs, data) {
  123.         if (Ext.isArray(rs)) {
  124.             for (var i=rs.length-1; i >= 0; i--) {
  125.                 if (Ext.isArray(data)) {
  126.                     this.update(rs.splice(i,1).shift(), data.splice(i,1).shift());
  127.                 }
  128.                 else {
  129.                     // weird...rs is an array but data isn't??  recurse but just send in the whole data object.
  130.                     // the else clause below will detect !this.isData and throw exception.
  131.                     this.update(rs.splice(i,1).shift(), data);
  132.                 }
  133.             }
  134.         }
  135.         else {
  136.             // If rs is NOT an array but data IS, see if data contains just 1 record.  If so extract it and carry on.
  137.             if (Ext.isArray(data) && data.length == 1) {
  138.                 data = data.shift();
  139.             }
  140.             if (this.isData(data)) {
  141.                 rs.fields.each(function(f) {
  142.                     if (data[f.name] !== f.defaultValue) {
  143.                         rs.data[f.name] = data[f.name];
  144.                     }
  145.                 });
  146.             }
  147.             rs.commit();
  148.         }
  149.     },
  150.     /**
  151.      * returns extracted, type-cast rows of data.  Iterates to call #extractValues for each row
  152.      * @param {Object[]/Object} data-root from server response
  153.      * @param {Boolean} returnRecords [false] Set true to return instances of Ext.data.Record
  154.      * @private
  155.      */
  156.     extractData : function(root, returnRecords) {
  157.         // A bit ugly this, too bad the Record's raw data couldn't be saved in a common property named "raw" or something.
  158.         var rawName = (this instanceof Ext.data.JsonReader) ? 'json' : 'node';
  159.         var rs = [];
  160.         // Had to add Check for XmlReader, #isData returns true if root is an Xml-object.  Want to check in order to re-factor
  161.         // #extractData into DataReader base, since the implementations are almost identical for JsonReader, XmlReader
  162.         if (this.isData(root) && !(this instanceof Ext.data.XmlReader)) {
  163.             root = [root];
  164.         }
  165.         var f       = this.recordType.prototype.fields,
  166.             fi      = f.items,
  167.             fl      = f.length,
  168.             rs      = [];
  169.         if (returnRecords === true) {
  170.             var Record = this.recordType;
  171.             for (var i = 0; i < root.length; i++) {
  172.                 var n = root[i];
  173.                 var record = new Record(this.extractValues(n, fi, fl), this.getId(n));
  174.                 record[rawName] = n;    // <-- There's implementation of ugly bit, setting the raw record-data.
  175.                 rs.push(record);
  176.             }
  177.         }
  178.         else {
  179.             for (var i = 0; i < root.length; i++) {
  180.                 var data = this.extractValues(root[i], fi, fl);
  181.                 data[this.meta.idProperty] = this.getId(root[i]);
  182.                 rs.push(data);
  183.             }
  184.         }
  185.         return rs;
  186.     },
  187.     /**
  188.      * Returns true if the supplied data-hash <b>looks</b> and quacks like data.  Checks to see if it has a key
  189.      * corresponding to idProperty defined in your DataReader config containing non-empty pk.
  190.      * @param {Object} data
  191.      * @return {Boolean}
  192.      */
  193.     isData : function(data) {
  194.         return (data && Ext.isObject(data) && !Ext.isEmpty(this.getId(data))) ? true : false;
  195.     },
  196.     // private function a store will createSequence upon
  197.     onMetaChange : function(meta){
  198.         delete this.ef;
  199.         this.meta = meta;
  200.         this.recordType = Ext.data.Record.create(meta.fields);
  201.         this.buildExtractors();
  202.     }
  203. };
  204. /**
  205.  * @class Ext.data.DataReader.Error
  206.  * @extends Ext.Error
  207.  * General error class for Ext.data.DataReader
  208.  */
  209. Ext.data.DataReader.Error = Ext.extend(Ext.Error, {
  210.     constructor : function(message, arg) {
  211.         this.arg = arg;
  212.         Ext.Error.call(this, message);
  213.     },
  214.     name: 'Ext.data.DataReader'
  215. });
  216. Ext.apply(Ext.data.DataReader.Error.prototype, {
  217.     lang : {
  218.         'update': "#update received invalid data from server.  Please see docs for DataReader#update and review your DataReader configuration.",
  219.         'realize': "#realize was called with invalid remote-data.  Please see the docs for DataReader#realize and review your DataReader configuration.",
  220.         'invalid-response': "#readResponse received an invalid response from the server."
  221.     }
  222. });