| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778 | 
							- <!DOCTYPE html>
 
- <html>
 
- <head>
 
-   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 
-   <title>The source code</title>
 
-   <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
 
-   <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
 
-   <style type="text/css">
 
-     .highlight { display: block; background-color: #ddd; }
 
-   </style>
 
-   <script type="text/javascript">
 
-     function highlight() {
 
-       document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
 
-     }
 
-   </script>
 
- </head>
 
- <body onload="prettyPrint(); highlight();">
 
-   <pre class="prettyprint lang-js"><span id='Ext-data-reader-Reader'>/**
 
- </span> * @author Ed Spencer
 
-  *
 
-  * Readers are used to interpret data to be loaded into a {@link Ext.data.Model Model} instance or a {@link
 
-  * Ext.data.Store Store} - often in response to an AJAX request. In general there is usually no need to create
 
-  * a Reader instance directly, since a Reader is almost always used together with a {@link Ext.data.proxy.Proxy Proxy},
 
-  * and is configured using the Proxy's {@link Ext.data.proxy.Proxy#cfg-reader reader} configuration property:
 
-  * 
 
-  *     Ext.create('Ext.data.Store', {
 
-  *         model: 'User',
 
-  *         proxy: {
 
-  *             type: 'ajax',
 
-  *             url : 'users.json',
 
-  *             reader: {
 
-  *                 type: 'json',
 
-  *                 root: 'users'
 
-  *             }
 
-  *         },
 
-  *     });
 
-  *     
 
-  * The above reader is configured to consume a JSON string that looks something like this:
 
-  *  
 
-  *     {
 
-  *         "success": true,
 
-  *         "users": [
 
-  *             { "name": "User 1" },
 
-  *             { "name": "User 2" }
 
-  *         ]
 
-  *     }
 
-  * 
 
-  *
 
-  * # Loading Nested Data
 
-  *
 
-  * Readers have the ability to automatically load deeply-nested data objects based on the {@link Ext.data.association.Association
 
-  * associations} configured on each Model. Below is an example demonstrating the flexibility of these associations in a
 
-  * fictional CRM system which manages a User, their Orders, OrderItems and Products. First we'll define the models:
 
-  *
 
-  *     Ext.define("User", {
 
-  *         extend: 'Ext.data.Model',
 
-  *         fields: [
 
-  *             'id', 'name'
 
-  *         ],
 
-  *
 
-  *         hasMany: {model: 'Order', name: 'orders'},
 
-  *
 
-  *         proxy: {
 
-  *             type: 'rest',
 
-  *             url : 'users.json',
 
-  *             reader: {
 
-  *                 type: 'json',
 
-  *                 root: 'users'
 
-  *             }
 
-  *         }
 
-  *     });
 
-  *
 
-  *     Ext.define("Order", {
 
-  *         extend: 'Ext.data.Model',
 
-  *         fields: [
 
-  *             'id', 'total'
 
-  *         ],
 
-  *
 
-  *         hasMany  : {model: 'OrderItem', name: 'orderItems', associationKey: 'order_items'},
 
-  *         belongsTo: 'User'
 
-  *     });
 
-  *
 
-  *     Ext.define("OrderItem", {
 
-  *         extend: 'Ext.data.Model',
 
-  *         fields: [
 
-  *             'id', 'price', 'quantity', 'order_id', 'product_id'
 
-  *         ],
 
-  *
 
-  *         belongsTo: ['Order', {model: 'Product', associationKey: 'product'}]
 
-  *     });
 
-  *
 
-  *     Ext.define("Product", {
 
-  *         extend: 'Ext.data.Model',
 
-  *         fields: [
 
-  *             'id', 'name'
 
-  *         ],
 
-  *
 
-  *         hasMany: 'OrderItem'
 
-  *     });
 
-  *
 
-  * This may be a lot to take in - basically a User has many Orders, each of which is composed of several OrderItems.
 
-  * Finally, each OrderItem has a single Product. This allows us to consume data like this:
 
-  *
 
-  *     {
 
-  *         "users": [
 
-  *             {
 
-  *                 "id": 123,
 
-  *                 "name": "Ed",
 
-  *                 "orders": [
 
-  *                     {
 
-  *                         "id": 50,
 
-  *                         "total": 100,
 
-  *                         "order_items": [
 
-  *                             {
 
-  *                                 "id"      : 20,
 
-  *                                 "price"   : 40,
 
-  *                                 "quantity": 2,
 
-  *                                 "product" : {
 
-  *                                     "id": 1000,
 
-  *                                     "name": "MacBook Pro"
 
-  *                                 }
 
-  *                             },
 
-  *                             {
 
-  *                                 "id"      : 21,
 
-  *                                 "price"   : 20,
 
-  *                                 "quantity": 3,
 
-  *                                 "product" : {
 
-  *                                     "id": 1001,
 
-  *                                     "name": "iPhone"
 
-  *                                 }
 
-  *                             }
 
-  *                         ]
 
-  *                     }
 
-  *                 ]
 
-  *             }
 
-  *         ]
 
-  *     }
 
-  *
 
-  * The JSON response is deeply nested - it returns all Users (in this case just 1 for simplicity's sake), all of the
 
-  * Orders for each User (again just 1 in this case), all of the OrderItems for each Order (2 order items in this case),
 
-  * and finally the Product associated with each OrderItem. Now we can read the data and use it as follows:
 
-  *
 
-  *     var store = Ext.create('Ext.data.Store', {
 
-  *         model: "User"
 
-  *     });
 
-  *
 
-  *     store.load({
 
-  *         callback: function() {
 
-  *             //the user that was loaded
 
-  *             var user = store.first();
 
-  *
 
-  *             console.log("Orders for " + user.get('name') + ":")
 
-  *
 
-  *             //iterate over the Orders for each User
 
-  *             user.orders().each(function(order) {
 
-  *                 console.log("Order ID: " + order.getId() + ", which contains items:");
 
-  *
 
-  *                 //iterate over the OrderItems for each Order
 
-  *                 order.orderItems().each(function(orderItem) {
 
-  *                     //we know that the Product data is already loaded, so we can use the synchronous getProduct
 
-  *                     //usually, we would use the asynchronous version (see {@link Ext.data.association.BelongsTo})
 
-  *                     var product = orderItem.getProduct();
 
-  *
 
-  *                     console.log(orderItem.get('quantity') + ' orders of ' + product.get('name'));
 
-  *                 });
 
-  *             });
 
-  *         }
 
-  *     });
 
-  *
 
-  * Running the code above results in the following:
 
-  *
 
-  *     Orders for Ed:
 
-  *     Order ID: 50, which contains items:
 
-  *     2 orders of MacBook Pro
 
-  *     3 orders of iPhone
 
-  */
 
- Ext.define('Ext.data.reader.Reader', {
 
-     requires: ['Ext.data.ResultSet', 'Ext.XTemplate'],
 
-     alternateClassName: ['Ext.data.Reader', 'Ext.data.DataReader'],
 
-     mixins: {
 
-         observable: 'Ext.util.Observable'
 
-     },
 
- <span id='Ext-data-reader-Reader-cfg-idProperty'>    /**
 
- </span>     * @cfg {String} idProperty
 
-      * Name of the property within a row object that contains a record identifier value. Defaults to the id of the
 
-      * model. If an idProperty is explicitly specified it will override the idProperty defined on the model.
 
-      */
 
- <span id='Ext-data-reader-Reader-cfg-totalProperty'>    /**
 
- </span>     * @cfg {String} [totalProperty="total"]
 
-      * Name of the property from which to retrieve the total number of records in the dataset. This is only needed if
 
-      * the whole dataset is not passed in one go, but is being paged from the remote server.
 
-      */
 
-     totalProperty: 'total',
 
- <span id='Ext-data-reader-Reader-cfg-successProperty'>    /**
 
- </span>     * @cfg {String} [successProperty="success"]
 
-      * Name of the property from which to retrieve the `success` attribute, the value of which indicates
 
-      * whether a given request succeeded or failed (typically a boolean or 'true'|'false'). See
 
-      * {@link Ext.data.proxy.Server}.{@link Ext.data.proxy.Server#exception exception} for additional information.
 
-      */
 
-     successProperty: 'success',
 
- <span id='Ext-data-reader-Reader-cfg-root'>    /**
 
- </span>     * @cfg {String} root
 
-      * The name of the property which contains the data items corresponding to the Model(s) for which this
 
-      * Reader is configured.  For JSON reader it's a property name (or a dot-separated list of property names
 
-      * if the root is nested).  For XML reader it's a CSS selector.  For Array reader the root is not applicable
 
-      * since the data is assumed to be a single-level array of arrays.
 
-      * 
 
-      * By default the natural root of the data will be used: the root JSON array, the root XML element, or the array.
 
-      *
 
-      * The data packet value for this property should be an empty array to clear the data or show no data.
 
-      */
 
-     root: '',
 
-     
 
- <span id='Ext-data-reader-Reader-cfg-messageProperty'>    /**
 
- </span>     * @cfg {String} messageProperty
 
-      * The name of the property which contains a response message. This property is optional.
 
-      */
 
-     
 
- <span id='Ext-data-reader-Reader-cfg-implicitIncludes'>    /**
 
- </span>     * @cfg {Boolean} [implicitIncludes=true]
 
-      * True to automatically parse models nested within other models in a response object. See the
 
-      * Ext.data.reader.Reader intro docs for full explanation.
 
-      */
 
-     implicitIncludes: true,
 
-     
 
- <span id='Ext-data-reader-Reader-cfg-readRecordsOnFailure'>    /**
 
- </span>     * @cfg {Boolean} [readRecordsOnFailure=true]
 
-      * True to extract the records from a data packet even if the {@link #successProperty} returns false.
 
-      */
 
-     readRecordsOnFailure: true,
 
-     
 
- <span id='Ext-data-reader-Reader-property-metaData'>    /**
 
- </span>     * @property {Object} metaData
 
-      * The raw meta data that was most recently read, if any. Meta data can include existing
 
-      * Reader config options like {@link #idProperty}, {@link #totalProperty}, etc. that get
 
-      * automatically applied to the Reader, and those can still be accessed directly from the Reader
 
-      * if needed. However, meta data is also often used to pass other custom data to be processed
 
-      * by application code. For example, it is common when reconfiguring the data model of a grid to
 
-      * also pass a corresponding column model config to be applied to the grid. Any such data will
 
-      * not get applied to the Reader directly (it just gets passed through and is ignored by Ext).
 
-      * This metaData property gives you access to all meta data that was passed, including any such
 
-      * custom data ignored by the reader.
 
-      * 
 
-      * This is a read-only property, and it will get replaced each time a new meta data object is
 
-      * passed to the reader. Note that typically you would handle proxy's
 
-      * {@link Ext.data.proxy.Proxy#metachange metachange} event which passes this exact same meta
 
-      * object to listeners. However this property is available if it's more convenient to access it
 
-      * via the reader directly in certain cases.
 
-      * @readonly
 
-      */
 
-     
 
-     /*
 
-      * @property {Boolean} isReader
 
-      * `true` in this class to identify an object as an instantiated Reader, or subclass thereof.
 
-      */
 
-     isReader: true,
 
-     // Private flag to the generated convertRecordData function to indicate whether to apply Field default
 
-     // values to fields for which no value is present in the raw data.
 
-     // This is set to false by a Server Proxy which is reading the response from a "create" or "update" operation.
 
-     applyDefaults: true,
 
-     lastFieldGeneration: null,
 
-     
 
- <span id='Ext-data-reader-Reader-method-constructor'>    /**
 
- </span>     * Creates new Reader.
 
-      * @param {Object} config (optional) Config object.
 
-      */
 
-     constructor: function(config) {
 
-         var me = this;
 
-         
 
-         me.mixins.observable.constructor.call(me, config);
 
-         me.fieldCount = 0;
 
-         me.model = Ext.ModelManager.getModel(me.model);
 
-         me.accessExpressionFn = Ext.Function.bind(me.createFieldAccessExpression, me);
 
-         // Extractors can only be calculated if the fields MixedCollection has been set.
 
-         // A Model may only complete its setup (set the prototype properties) after asynchronous loading
 
-         // which would mean that there may be no "fields"
 
-         // If this happens, the load callback will call proxy.setModel which calls reader.setModel which
 
-         // triggers buildExtractors.
 
-         if (me.model && me.model.prototype.fields) {
 
-             me.buildExtractors();
 
-         }
 
-         this.addEvents(
 
- <span id='Ext-data-reader-Reader-event-exception'>            /**
 
- </span>             * @event
 
-              * Fires when the reader receives improperly encoded data from the server
 
-              * @param {Ext.data.reader.Reader} reader A reference to this reader
 
-              * @param {XMLHttpRequest} response The XMLHttpRequest response object
 
-              * @param {Ext.data.ResultSet} error The error object
 
-              */
 
-             'exception'
 
-         );
 
-     },
 
- <span id='Ext-data-reader-Reader-method-setModel'>    /**
 
- </span>     * Sets a new model for the reader.
 
-      * @private
 
-      * @param {Object} model The model to set.
 
-      * @param {Boolean} setOnProxy True to also set on the Proxy, if one is configured
 
-      */
 
-     setModel: function(model, setOnProxy) {
 
-         var me = this;
 
-         
 
-         me.model = Ext.ModelManager.getModel(model);
 
-         me.buildExtractors(true);
 
-         
 
-         if (setOnProxy && me.proxy) {
 
-             me.proxy.setModel(me.model, true);
 
-         }
 
-     },
 
- <span id='Ext-data-reader-Reader-method-read'>    /**
 
- </span>     * Reads the given response object. This method normalizes the different types of response object that may be passed to it.
 
-      * If it's an XMLHttpRequest object, hand off to the subclass' {@link #getResponseData} method.
 
-      * Else, hand off the reading of records to the {@link #readRecords} method.
 
-      * @param {Object} response The response object. This may be either an XMLHttpRequest object or a plain JS object
 
-      * @return {Ext.data.ResultSet} The parsed or default ResultSet object
 
-      */
 
-     read: function(response) {
 
-         var data;
 
-         if (response) {
 
-             data = response.responseText ? this.getResponseData(response) : this.readRecords(response);
 
-         }
 
-         return data || this.nullResultSet;
 
-     },
 
- <span id='Ext-data-reader-Reader-method-readRecords'>    /**
 
- </span>     * Abstracts common functionality used by all Reader subclasses. Each subclass is expected to call this function
 
-      * before running its own logic and returning the Ext.data.ResultSet instance. For most Readers additional
 
-      * processing should not be needed.
 
-      * @param {Object} data The raw data object
 
-      * @return {Ext.data.ResultSet} A ResultSet object
 
-      */
 
-     readRecords: function(data) {
 
-         var me = this,
 
-             success,
 
-             recordCount,
 
-             records,
 
-             root,
 
-             total,
 
-             value,
 
-             message;
 
-         
 
-         /*
 
-          * We check here whether fields collection has changed since the last read.
 
-          * This works around an issue when a Model is used for both a Tree and another
 
-          * source, because the tree decorates the model with extra fields and it causes
 
-          * issues because the readers aren't notified.
 
-          */
 
-         if (me.lastFieldGeneration !== me.model.prototype.fields.generation) {
 
-             me.buildExtractors(true);
 
-         }
 
-         
 
- <span id='Ext-data-reader-Reader-property-rawData'>        /**
 
- </span>         * @property {Object} rawData
 
-          * The raw data object that was last passed to {@link #readRecords}. Stored for further processing if needed.
 
-          */
 
-         me.rawData = data;
 
-         data = me.getData(data);
 
-         
 
-         success = true;
 
-         recordCount = 0;
 
-         records = [];
 
-             
 
-         if (me.successProperty) {
 
-             value = me.getSuccess(data);
 
-             if (value === false || value === 'false') {
 
-                 success = false;
 
-             }
 
-         }
 
-         
 
-         if (me.messageProperty) {
 
-             message = me.getMessage(data);
 
-         }
 
-         
 
-         // Only try and extract other data if call was successful
 
-         if (me.readRecordsOnFailure || success) {
 
-             // If we pass an array as the data, we dont use getRoot on the data.
 
-             // Instead the root equals to the data.
 
-             root = Ext.isArray(data) ? data : me.getRoot(data);
 
-             
 
-             if (root) {
 
-                 total = root.length;
 
-             }
 
-           if (me.totalProperty) {
 
-                 value = parseInt(me.getTotal(data), 10);
 
-                 if (!isNaN(value)) {
 
-                     total = value;
 
-                 }
 
-             }
 
-            if (root) {
 
-                 records = me.extractData(root);
 
-                 recordCount = records.length;
 
-             }
 
-         }
 
-         return new Ext.data.ResultSet({
 
-             total  : total || recordCount,
 
-             count  : recordCount,
 
-             records: records,
 
-             success: success,
 
-             message: message
 
-         });
 
-     },
 
- <span id='Ext-data-reader-Reader-method-extractData'>    /**
 
- </span>     * Returns extracted, type-cast rows of data.
 
-      * @param {Object[]/Object} root from server response
 
-      * @return {Array} An array of records containing the extracted data
 
-      * @private
 
-      */
 
-     extractData : function(root) {
 
-         var me = this,
 
-             records = [],
 
-             Model   = me.model,
 
-             length  = root.length,
 
-             convertedValues, node, record, i;
 
-             
 
-         if (!root.length && Ext.isObject(root)) {
 
-             root = [root];
 
-             length = 1;
 
-         }
 
-         for (i = 0; i < length; i++) {
 
-             node = root[i];
 
-             if (!node.isModel) { 
 
-                 // Create a record with an empty data object.
 
-                 // Populate that data object by extracting and converting field values from raw data
 
-                 record = new Model(undefined, me.getId(node), node, convertedValues = {});
 
-                 // If the server did not include an id in the response data, the Model constructor will mark the record as phantom.
 
-                 // We  need to set phantom to false here because records created from a server response using a reader by definition are not phantom records.
 
-                 record.phantom = false;
 
-                 // Use generated function to extract all fields at once
 
-                 me.convertRecordData(convertedValues, node, record);
 
-                 records.push(record);
 
-                 
 
-                 if (me.implicitIncludes) {
 
-                     me.readAssociated(record, node);
 
-                 }
 
-             } else {
 
-                 // If we're given a model instance in the data, just push it on
 
-                 // without doing any conversion
 
-                 records.push(node);
 
-             }
 
-         }
 
-         return records;
 
-     },
 
-     
 
- <span id='Ext-data-reader-Reader-method-readAssociated'>    /**
 
- </span>     * @private
 
-      * Loads a record's associations from the data object. This prepopulates hasMany and belongsTo associations
 
-      * on the record provided.
 
-      * @param {Ext.data.Model} record The record to load associations for
 
-      * @param {Object} data The data object
 
-      * @return {String} Return value description
 
-      */
 
-     readAssociated: function(record, data) {
 
-         var associations = record.associations.items,
 
-             i            = 0,
 
-             length       = associations.length,
 
-             association, associationData, proxy, reader;
 
-         
 
-         for (; i < length; i++) {
 
-             association     = associations[i];
 
-             associationData = this.getAssociatedDataRoot(data, association.associationKey || association.name);
 
-             
 
-             if (associationData) {
 
-                 reader = association.getReader();
 
-                 if (!reader) {
 
-                     proxy = association.associatedModel.proxy;
 
-                     // if the associated model has a Reader already, use that, otherwise attempt to create a sensible one
 
-                     if (proxy) {
 
-                         reader = proxy.getReader();
 
-                     } else {
 
-                         reader = new this.constructor({
 
-                             model: association.associatedName
 
-                         });
 
-                     }
 
-                 }
 
-                 association.read(record, reader, associationData);
 
-             }  
 
-         }
 
-     },
 
-     
 
- <span id='Ext-data-reader-Reader-method-getAssociatedDataRoot'>    /**
 
- </span>     * @private
 
-      * Used internally by {@link #readAssociated}. Given a data object (which could be json, xml etc) for a specific
 
-      * record, this should return the relevant part of that data for the given association name. This is only really
 
-      * needed to support the XML Reader, which has to do a query to get the associated data object
 
-      * @param {Object} data The raw data object
 
-      * @param {String} associationName The name of the association to get data for (uses associationKey if present)
 
-      * @return {Object} The root
 
-      */
 
-     getAssociatedDataRoot: function(data, associationName) {
 
-         return data[associationName];
 
-     },
 
-     
 
-     getFields: function() {
 
-         return this.model.prototype.fields.items;
 
-     },
 
- <span id='Ext-data-reader-Reader-method-getData'>    /**
 
- </span>     * @private
 
-      * By default this function just returns what is passed to it. It can be overridden in a subclass
 
-      * to return something else. See XmlReader for an example.
 
-      * @param {Object} data The data object
 
-      * @return {Object} The normalized data object
 
-      */
 
-     getData: function(data) {
 
-         return data;
 
-     },
 
- <span id='Ext-data-reader-Reader-method-getRoot'>    /**
 
- </span>     * @private
 
-      * This will usually need to be implemented in a subclass. Given a generic data object (the type depends on the type
 
-      * of data we are reading), this function should return the object as configured by the Reader's 'root' meta data config.
 
-      * See XmlReader's getRoot implementation for an example. By default the same data object will simply be returned.
 
-      * @param {Object} data The data object
 
-      * @return {Object} The same data object
 
-      */
 
-     getRoot: function(data) {
 
-         return data;
 
-     },
 
- <span id='Ext-data-reader-Reader-method-getResponseData'>    /**
 
- </span>     * Takes a raw response object (as passed to the {@link #read} method) and returns the useful data
 
-      * segment from it. This must be implemented by each subclass.
 
-      * @param {Object} response The response object
 
-      * @return {Ext.data.ResultSet} A ResultSet object
 
-      */
 
-     getResponseData: function(response) {
 
-         //<debug>
 
-         Ext.Error.raise("getResponseData must be implemented in the Ext.data.reader.Reader subclass");
 
-         //</debug>
 
-     },
 
- <span id='Ext-data-reader-Reader-method-onMetaChange'>    /**
 
- </span>     * @private
 
-      * Reconfigures the meta data tied to this Reader
 
-      */
 
-     onMetaChange : function(meta) {
 
-         var me = this,
 
-             fields = meta.fields || me.getFields(),
 
-             newModel,
 
-             clientIdProperty;
 
-         
 
-         // save off the raw meta data
 
-         me.metaData = meta;
 
-         
 
-         // set any reader-specific configs from meta if available
 
-         me.root = meta.root || me.root;
 
-         me.idProperty = meta.idProperty || me.idProperty;
 
-         me.totalProperty = meta.totalProperty || me.totalProperty;
 
-         me.successProperty = meta.successProperty || me.successProperty;
 
-         me.messageProperty = meta.messageProperty || me.messageProperty;
 
-         clientIdProperty = meta.clientIdProperty;
 
-         if (me.model) {
 
-             me.model.setFields(fields, me.idProperty, clientIdProperty);
 
-             me.setModel(me.model, true);
 
-         }
 
-         else {
 
-             newModel = Ext.define("Ext.data.reader.Json-Model" + Ext.id(), {
 
-                 extend: 'Ext.data.Model',
 
-                 fields: fields,
 
-                 clientIdProperty: clientIdProperty
 
-             });
 
-             if (me.idProperty) {
 
-                 // We only do this if the reader actually has a custom idProperty set,
 
-                 // otherwise let the model use its own default value. It is valid for
 
-                 // the reader idProperty to be undefined, in which case it will use the
 
-                 // model's idProperty (in getIdProperty()).
 
-                 newModel.idProperty = me.idProperty;
 
-             }
 
-             me.setModel(newModel, true);
 
-         }
 
-     },
 
-     
 
- <span id='Ext-data-reader-Reader-method-getIdProperty'>    /**
 
- </span>     * Get the idProperty to use for extracting data
 
-      * @private
 
-      * @return {String} The id property
 
-      */
 
-     getIdProperty: function(){
 
-         return this.idProperty || this.model.prototype.idProperty;
 
-     },
 
- <span id='Ext-data-reader-Reader-method-buildExtractors'>    /**
 
- </span>     * @private
 
-      * This builds optimized functions for retrieving record data and meta data from an object.
 
-      * Subclasses may need to implement their own getRoot function.
 
-      * @param {Boolean} [force=false] True to automatically remove existing extractor functions first
 
-      */
 
-     buildExtractors: function(force) {
 
-         var me          = this,
 
-             idProp      = me.getIdProperty(),
 
-             totalProp   = me.totalProperty,
 
-             successProp = me.successProperty,
 
-             messageProp = me.messageProperty,
 
-             accessor,
 
-             idField,
 
-             map;
 
-             
 
-         if (force === true) {
 
-             delete me.convertRecordData;
 
-         }
 
-         
 
-         if (me.convertRecordData) {
 
-             return;
 
-         }   
 
-         //build the extractors for all the meta data
 
-         if (totalProp) {
 
-             me.getTotal = me.createAccessor(totalProp);
 
-         }
 
-         if (successProp) {
 
-             me.getSuccess = me.createAccessor(successProp);
 
-         }
 
-         if (messageProp) {
 
-             me.getMessage = me.createAccessor(messageProp);
 
-         }
 
-         if (idProp) {
 
-             idField = me.model.prototype.fields.get(idProp);
 
-             if (idField) {
 
-                 map = idField.mapping;
 
-                 idProp = (map !== undefined && map !== null) ? map : idProp;
 
-             }
 
-             accessor = me.createAccessor(idProp);
 
-             me.getId = function(record) {
 
-                 var id = accessor.call(me, record);
 
-                 return (id === undefined || id === '') ? null : id;
 
-             };
 
-         } else {
 
-             me.getId = function() {
 
-                 return null;
 
-             };
 
-         }
 
-         me.convertRecordData = me.buildRecordDataExtractor();
 
-         me.lastFieldGeneration = me.model.prototype.fields.generation;
 
-     },
 
-     recordDataExtractorTemplate : [
 
-         'var me = this\n',
 
-         '    ,fields = me.model.prototype.fields\n',
 
-         '    ,value\n',
 
-         '    ,internalId\n',
 
-         '<tpl for="fields">',
 
-         '    ,__field{#} = fields.get("{name}")\n',
 
-         '</tpl>', ';\n',
 
-         'return function(dest, source, record) {\n',
 
-         '<tpl for="fields">',
 
-         // createFieldAccessExpression must be implemented in subclasses to extract data from the source object in the correct way
 
-         '    value = {[ this.createFieldAccessExpression(values, "__field" + xindex, "source") ]};\n',
 
-         // Code for processing a source property when a custom convert is defined
 
-             '<tpl if="hasCustomConvert">',
 
-         '    dest["{name}"] = value === undefined ? __field{#}.convert(__field{#}.defaultValue, record) : __field{#}.convert(value, record);\n',
 
-         // Code for processing a source property when there is a default value
 
-             '<tpl elseif="defaultValue !== undefined">',
 
-         '    if (value === undefined) {\n',
 
-         '        if (me.applyDefaults) {\n',
 
-                 '<tpl if="convert">',
 
-         '            dest["{name}"] = __field{#}.convert(__field{#}.defaultValue, record);\n',
 
-                 '<tpl else>',
 
-         '            dest["{name}"] = __field{#}.defaultValue\n',
 
-                 '</tpl>',
 
-         '        };\n',
 
-         '    } else {\n',
 
-                 '<tpl if="convert">',
 
-         '        dest["{name}"] = __field{#}.convert(value, record);\n',
 
-                 '<tpl else>',
 
-         '        dest["{name}"] = value;\n',
 
-                 '</tpl>',
 
-         '    };',
 
-         // Code for processing a source property value when there is no default value
 
-             '<tpl else>',
 
-         '    if (value !== undefined) {\n',
 
-                 '<tpl if="convert">',
 
-         '        dest["{name}"] = __field{#}.convert(value, record);\n',
 
-                 '<tpl else>',
 
-         '        dest["{name}"] = value;\n',
 
-                 '</tpl>',
 
-         '    }\n',
 
-             '</tpl>',
 
-         '</tpl>',
 
-         // set the client id as the internalId of the record.
 
-         // clientId handles the case where a client side record did not previously exist on the server,
 
-         // so the server is passing back a client id that can be used to pair the server side record up with the client record
 
-         '<tpl if="clientIdProp">',
 
-         '    if (record && (internalId = {[ this.createFieldAccessExpression(\{mapping: values.clientIdProp\}, null, "source") ]})) {\n',
 
-         '        record.{["internalId"]} = internalId;\n',
 
-         '    }\n',
 
-         '</tpl>',
 
-         '};'
 
-     ],
 
- <span id='Ext-data-reader-Reader-method-buildRecordDataExtractor'>    /**
 
- </span>     * @private
 
-      * Return a function which will read a raw row object in the format this Reader accepts, and populates
 
-      * a record's data object with converted data values.
 
-      *
 
-      * The returned function must be passed the following parameters:
 
-      *
 
-      * - dest A record's empty data object into which the new field value properties are injected.
 
-      * - source A raw row data object of whatever type this Reader consumes
 
-      * - record The record which is being populated.
 
-      *
 
-      */
 
-     buildRecordDataExtractor: function() {
 
-         var me = this,
 
-             modelProto = me.model.prototype,
 
-             templateData = {
 
-                 clientIdProp: modelProto.clientIdProperty,
 
-                 fields: modelProto.fields.items
 
-             };
 
-         me.recordDataExtractorTemplate.createFieldAccessExpression = me.accessExpressionFn;
 
-         // Here we are creating a new Function and invoking it immediately in the scope of this Reader
 
-         // It declares several vars capturing the configured context of this Reader, and returns a function
 
-         // which, when passed a record data object, a raw data row in the format this Reader is configured to read,
 
-         // and the record which is being created, will populate the record's data object from the raw row data.
 
-         return Ext.functionFactory(me.recordDataExtractorTemplate.apply(templateData)).call(me);
 
-     },
 
-     destroyReader: function() {
 
-         var me = this;
 
-         delete me.proxy;
 
-         delete me.model;
 
-         delete me.convertRecordData;
 
-         delete me.getId;
 
-         delete me.getTotal;
 
-         delete me.getSuccess;
 
-         delete me.getMessage;
 
-     }
 
- }, function() {
 
-     var proto = this.prototype;
 
-     Ext.apply(proto, {
 
-         // Private. Empty ResultSet to return when response is falsy (null|undefined|empty string)
 
-         nullResultSet: new Ext.data.ResultSet({
 
-             total  : 0,
 
-             count  : 0,
 
-             records: [],
 
-             success: true
 
-         }),
 
-         recordDataExtractorTemplate: new Ext.XTemplate(proto.recordDataExtractorTemplate)
 
-     });
 
- });
 
- </pre>
 
- </body>
 
- </html>
 
 
  |