| 1 | 
           efrain | 
           1 | 
           YUI.add('dataschema-json', function (Y, NAME) {
  | 
        
        
            | 
            | 
           2 | 
              | 
        
        
            | 
            | 
           3 | 
           /**
  | 
        
        
            | 
            | 
           4 | 
           Provides a DataSchema implementation which can be used to work with JSON data.
  | 
        
        
            | 
            | 
           5 | 
              | 
        
        
            | 
            | 
           6 | 
           @module dataschema
  | 
        
        
            | 
            | 
           7 | 
           @submodule dataschema-json
  | 
        
        
            | 
            | 
           8 | 
           **/
  | 
        
        
            | 
            | 
           9 | 
              | 
        
        
            | 
            | 
           10 | 
           /**
  | 
        
        
            | 
            | 
           11 | 
           Provides a DataSchema implementation which can be used to work with JSON data.
  | 
        
        
            | 
            | 
           12 | 
              | 
        
        
            | 
            | 
           13 | 
           See the `apply` method for usage.
  | 
        
        
            | 
            | 
           14 | 
              | 
        
        
            | 
            | 
           15 | 
           @class DataSchema.JSON
  | 
        
        
            | 
            | 
           16 | 
           @extends DataSchema.Base
  | 
        
        
            | 
            | 
           17 | 
           @static
  | 
        
        
            | 
            | 
           18 | 
           **/
  | 
        
        
            | 
            | 
           19 | 
           var LANG = Y.Lang,
  | 
        
        
            | 
            | 
           20 | 
               isFunction = LANG.isFunction,
  | 
        
        
            | 
            | 
           21 | 
               isObject   = LANG.isObject,
  | 
        
        
            | 
            | 
           22 | 
               isArray    = LANG.isArray,
  | 
        
        
            | 
            | 
           23 | 
               // TODO: I don't think the calls to Base.* need to be done via Base since
  | 
        
        
            | 
            | 
           24 | 
               // Base is mixed into SchemaJSON.  Investigate for later.
  | 
        
        
            | 
            | 
           25 | 
               Base       = Y.DataSchema.Base,
  | 
        
        
            | 
            | 
           26 | 
              | 
        
        
            | 
            | 
           27 | 
               SchemaJSON;
  | 
        
        
            | 
            | 
           28 | 
              | 
        
        
            | 
            | 
           29 | 
           SchemaJSON = {
  | 
        
        
            | 
            | 
           30 | 
              | 
        
        
            | 
            | 
           31 | 
           /////////////////////////////////////////////////////////////////////////////
  | 
        
        
            | 
            | 
           32 | 
           //
  | 
        
        
            | 
            | 
           33 | 
           // DataSchema.JSON static methods
  | 
        
        
            | 
            | 
           34 | 
           //
  | 
        
        
            | 
            | 
           35 | 
           /////////////////////////////////////////////////////////////////////////////
  | 
        
        
            | 
            | 
           36 | 
               /**
  | 
        
        
            | 
            | 
           37 | 
                * Utility function converts JSON locator strings into walkable paths
  | 
        
        
            | 
            | 
           38 | 
                *
  | 
        
        
            | 
            | 
           39 | 
                * @method getPath
  | 
        
        
            | 
            | 
           40 | 
                * @param locator {String} JSON value locator.
  | 
        
        
            | 
            | 
           41 | 
                * @return {String[]} Walkable path to data value.
  | 
        
        
            | 
            | 
           42 | 
                * @static
  | 
        
        
            | 
            | 
           43 | 
                */
  | 
        
        
            | 
            | 
           44 | 
               getPath: function(locator) {
  | 
        
        
            | 
            | 
           45 | 
                   var path = null,
  | 
        
        
            | 
            | 
           46 | 
                       keys = [],
  | 
        
        
            | 
            | 
           47 | 
                       i = 0;
  | 
        
        
            | 
            | 
           48 | 
              | 
        
        
            | 
            | 
           49 | 
                   if (locator) {
  | 
        
        
            | 
            | 
           50 | 
                       // Strip the ["string keys"] and [1] array indexes
  | 
        
        
            | 
            | 
           51 | 
                       // TODO: the first two steps can probably be reduced to one with
  | 
        
        
            | 
            | 
           52 | 
                       // /\[\s*(['"])?(.*?)\1\s*\]/g, but the array indices would be
  | 
        
        
            | 
            | 
           53 | 
                       // stored as strings.  This is not likely an issue.
  | 
        
        
            | 
            | 
           54 | 
                       locator = locator.
  | 
        
        
            | 
            | 
           55 | 
                           replace(/\[\s*(['"])(.*?)\1\s*\]/g,
  | 
        
        
            | 
            | 
           56 | 
                           function (x,$1,$2) {keys[i]=$2;return '.@'+(i++);}).
  | 
        
        
            | 
            | 
           57 | 
                           replace(/\[(\d+)\]/g,
  | 
        
        
            | 
            | 
           58 | 
                           function (x,$1) {keys[i]=parseInt($1,10)|0;return '.@'+(i++);}).
  | 
        
        
            | 
            | 
           59 | 
                           replace(/^\./,''); // remove leading dot
  | 
        
        
            | 
            | 
           60 | 
              | 
        
        
            | 
            | 
           61 | 
                       // Validate against problematic characters.
  | 
        
        
            | 
            | 
           62 | 
                       // commented out because the path isn't sent to eval, so it
  | 
        
        
            | 
            | 
           63 | 
                       // should be safe. I'm not sure what makes a locator invalid.
  | 
        
        
            | 
            | 
           64 | 
                       //if (!/[^\w\.\$@]/.test(locator)) {
  | 
        
        
            | 
            | 
           65 | 
                       path = locator.split('.');
  | 
        
        
            | 
            | 
           66 | 
                       for (i=path.length-1; i >= 0; --i) {
  | 
        
        
            | 
            | 
           67 | 
                           if (path[i].charAt(0) === '@') {
  | 
        
        
            | 
            | 
           68 | 
                               path[i] = keys[parseInt(path[i].substr(1),10)];
  | 
        
        
            | 
            | 
           69 | 
                           }
  | 
        
        
            | 
            | 
           70 | 
                       }
  | 
        
        
            | 
            | 
           71 | 
                       /*}
  | 
        
        
            | 
            | 
           72 | 
                       else {
  | 
        
        
            | 
            | 
           73 | 
                           Y.log("Invalid locator: " + locator, "error", "dataschema-json");
  | 
        
        
            | 
            | 
           74 | 
                       }
  | 
        
        
            | 
            | 
           75 | 
                       */
  | 
        
        
            | 
            | 
           76 | 
                   }
  | 
        
        
            | 
            | 
           77 | 
                   return path;
  | 
        
        
            | 
            | 
           78 | 
               },
  | 
        
        
            | 
            | 
           79 | 
              | 
        
        
            | 
            | 
           80 | 
               /**
  | 
        
        
            | 
            | 
           81 | 
                * Utility function to walk a path and return the value located there.
  | 
        
        
            | 
            | 
           82 | 
                *
  | 
        
        
            | 
            | 
           83 | 
                * @method getLocationValue
  | 
        
        
            | 
            | 
           84 | 
                * @param path {String[]} Locator path.
  | 
        
        
            | 
            | 
           85 | 
                * @param data {String} Data to traverse.
  | 
        
        
            | 
            | 
           86 | 
                * @return {Object} Data value at location.
  | 
        
        
            | 
            | 
           87 | 
                * @static
  | 
        
        
            | 
            | 
           88 | 
                */
  | 
        
        
            | 
            | 
           89 | 
               getLocationValue: function (path, data) {
  | 
        
        
            | 
            | 
           90 | 
                   var i = 0,
  | 
        
        
            | 
            | 
           91 | 
                       len = path.length;
  | 
        
        
            | 
            | 
           92 | 
                   for (;i<len;i++) {
  | 
        
        
            | 
            | 
           93 | 
                       if (isObject(data) && (path[i] in data)) {
  | 
        
        
            | 
            | 
           94 | 
                           data = data[path[i]];
  | 
        
        
            | 
            | 
           95 | 
                       } else {
  | 
        
        
            | 
            | 
           96 | 
                           data = undefined;
  | 
        
        
            | 
            | 
           97 | 
                           break;
  | 
        
        
            | 
            | 
           98 | 
                       }
  | 
        
        
            | 
            | 
           99 | 
                   }
  | 
        
        
            | 
            | 
           100 | 
                   return data;
  | 
        
        
            | 
            | 
           101 | 
               },
  | 
        
        
            | 
            | 
           102 | 
              | 
        
        
            | 
            | 
           103 | 
               /**
  | 
        
        
            | 
            | 
           104 | 
               Applies a schema to an array of data located in a JSON structure, returning
  | 
        
        
            | 
            | 
           105 | 
               a normalized object with results in the `results` property. Additional
  | 
        
        
            | 
            | 
           106 | 
               information can be parsed out of the JSON for inclusion in the `meta`
  | 
        
        
            | 
            | 
           107 | 
               property of the response object.  If an error is encountered during
  | 
        
        
            | 
            | 
           108 | 
               processing, an `error` property will be added.
  | 
        
        
            | 
            | 
           109 | 
              | 
        
        
            | 
            | 
           110 | 
               The input _data_ is expected to be an object or array.  If it is a string,
  | 
        
        
            | 
            | 
           111 | 
               it will be passed through `Y.JSON.parse()`.
  | 
        
        
            | 
            | 
           112 | 
              | 
        
        
            | 
            | 
           113 | 
               If _data_ contains an array of data records to normalize, specify the
  | 
        
        
            | 
            | 
           114 | 
               _schema.resultListLocator_ as a dot separated path string just as you would
  | 
        
        
            | 
            | 
           115 | 
               reference it in JavaScript.  So if your _data_ object has a record array at
  | 
        
        
            | 
            | 
           116 | 
               _data.response.results_, use _schema.resultListLocator_ =
  | 
        
        
            | 
            | 
           117 | 
               "response.results". Bracket notation can also be used for array indices or
  | 
        
        
            | 
            | 
           118 | 
               object properties (e.g. "response['results']");  This is called a "path
  | 
        
        
            | 
            | 
           119 | 
               locator"
  | 
        
        
            | 
            | 
           120 | 
              | 
        
        
            | 
            | 
           121 | 
               Field data in the result list is extracted with field identifiers in
  | 
        
        
            | 
            | 
           122 | 
               _schema.resultFields_.  Field identifiers are objects with the following
  | 
        
        
            | 
            | 
           123 | 
               properties:
  | 
        
        
            | 
            | 
           124 | 
              | 
        
        
            | 
            | 
           125 | 
                 * `key`   : <strong>(required)</strong> The path locator (String)
  | 
        
        
            | 
            | 
           126 | 
                 * `parser`: A function or the name of a function on `Y.Parsers` used
  | 
        
        
            | 
            | 
           127 | 
                       to convert the input value into a normalized type.  Parser
  | 
        
        
            | 
            | 
           128 | 
                       functions are passed the value as input and are expected to
  | 
        
        
            | 
            | 
           129 | 
                       return a value.
  | 
        
        
            | 
            | 
           130 | 
              | 
        
        
            | 
            | 
           131 | 
               If no value parsing is needed, you can use path locators (strings)
  | 
        
        
            | 
            | 
           132 | 
               instead of field identifiers (objects) -- see example below.
  | 
        
        
            | 
            | 
           133 | 
              | 
        
        
            | 
            | 
           134 | 
               If no processing of the result list array is needed, _schema.resultFields_
  | 
        
        
            | 
            | 
           135 | 
               can be omitted; the `response.results` will point directly to the array.
  | 
        
        
            | 
            | 
           136 | 
              | 
        
        
            | 
            | 
           137 | 
               If the result list contains arrays, `response.results` will contain an
  | 
        
        
            | 
            | 
           138 | 
               array of objects with key:value pairs assuming the fields in
  | 
        
        
            | 
            | 
           139 | 
               _schema.resultFields_ are ordered in accordance with the data array
  | 
        
        
            | 
            | 
           140 | 
               values.
  | 
        
        
            | 
            | 
           141 | 
              | 
        
        
            | 
            | 
           142 | 
               If the result list contains objects, the identified _schema.resultFields_
  | 
        
        
            | 
            | 
           143 | 
               will be used to extract a value from those objects for the output result.
  | 
        
        
            | 
            | 
           144 | 
              | 
        
        
            | 
            | 
           145 | 
               To extract additional information from the JSON, include an array of
  | 
        
        
            | 
            | 
           146 | 
               path locators in _schema.metaFields_.  The collected values will be
  | 
        
        
            | 
            | 
           147 | 
               stored in `response.meta`.
  | 
        
        
            | 
            | 
           148 | 
              | 
        
        
            | 
            | 
           149 | 
              | 
        
        
            | 
            | 
           150 | 
               @example
  | 
        
        
            | 
            | 
           151 | 
                   // Process array of arrays
  | 
        
        
            | 
            | 
           152 | 
                   var schema = {
  | 
        
        
            | 
            | 
           153 | 
                           resultListLocator: 'produce.fruit',
  | 
        
        
            | 
            | 
           154 | 
                           resultFields: [ 'name', 'color' ]
  | 
        
        
            | 
            | 
           155 | 
                       },
  | 
        
        
            | 
            | 
           156 | 
                       data = {
  | 
        
        
            | 
            | 
           157 | 
                           produce: {
  | 
        
        
            | 
            | 
           158 | 
                               fruit: [
  | 
        
        
            | 
            | 
           159 | 
                                   [ 'Banana', 'yellow' ],
  | 
        
        
            | 
            | 
           160 | 
                                   [ 'Orange', 'orange' ],
  | 
        
        
            | 
            | 
           161 | 
                                   [ 'Eggplant', 'purple' ]
  | 
        
        
            | 
            | 
           162 | 
                               ]
  | 
        
        
            | 
            | 
           163 | 
                           }
  | 
        
        
            | 
            | 
           164 | 
                       };
  | 
        
        
            | 
            | 
           165 | 
              | 
        
        
            | 
            | 
           166 | 
                   var response = Y.DataSchema.JSON.apply(schema, data);
  | 
        
        
            | 
            | 
           167 | 
              | 
        
        
            | 
            | 
           168 | 
                   // response.results[0] is { name: "Banana", color: "yellow" }
  | 
        
        
            | 
            | 
           169 | 
              | 
        
        
            | 
            | 
           170 | 
              | 
        
        
            | 
            | 
           171 | 
                   // Process array of objects + some metadata
  | 
        
        
            | 
            | 
           172 | 
                   schema.metaFields = [ 'lastInventory' ];
  | 
        
        
            | 
            | 
           173 | 
              | 
        
        
            | 
            | 
           174 | 
                   data = {
  | 
        
        
            | 
            | 
           175 | 
                       produce: {
  | 
        
        
            | 
            | 
           176 | 
                           fruit: [
  | 
        
        
            | 
            | 
           177 | 
                               { name: 'Banana', color: 'yellow', price: '1.96' },
  | 
        
        
            | 
            | 
           178 | 
                               { name: 'Orange', color: 'orange', price: '2.04' },
  | 
        
        
            | 
            | 
           179 | 
                               { name: 'Eggplant', color: 'purple', price: '4.31' }
  | 
        
        
            | 
            | 
           180 | 
                           ]
  | 
        
        
            | 
            | 
           181 | 
                       },
  | 
        
        
            | 
            | 
           182 | 
                       lastInventory: '2011-07-19'
  | 
        
        
            | 
            | 
           183 | 
                   };
  | 
        
        
            | 
            | 
           184 | 
              | 
        
        
            | 
            | 
           185 | 
                   response = Y.DataSchema.JSON.apply(schema, data);
  | 
        
        
            | 
            | 
           186 | 
              | 
        
        
            | 
            | 
           187 | 
                   // response.results[0] is { name: "Banana", color: "yellow" }
  | 
        
        
            | 
            | 
           188 | 
                   // response.meta.lastInventory is '2001-07-19'
  | 
        
        
            | 
            | 
           189 | 
              | 
        
        
            | 
            | 
           190 | 
              | 
        
        
            | 
            | 
           191 | 
                   // Use parsers
  | 
        
        
            | 
            | 
           192 | 
                   schema.resultFields = [
  | 
        
        
            | 
            | 
           193 | 
                       {
  | 
        
        
            | 
            | 
           194 | 
                           key: 'name',
  | 
        
        
            | 
            | 
           195 | 
                           parser: function (val) { return val.toUpperCase(); }
  | 
        
        
            | 
            | 
           196 | 
                       },
  | 
        
        
            | 
            | 
           197 | 
                       {
  | 
        
        
            | 
            | 
           198 | 
                           key: 'price',
  | 
        
        
            | 
            | 
           199 | 
                           parser: 'number' // Uses Y.Parsers.number
  | 
        
        
            | 
            | 
           200 | 
                       }
  | 
        
        
            | 
            | 
           201 | 
                   ];
  | 
        
        
            | 
            | 
           202 | 
              | 
        
        
            | 
            | 
           203 | 
                   response = Y.DataSchema.JSON.apply(schema, data);
  | 
        
        
            | 
            | 
           204 | 
              | 
        
        
            | 
            | 
           205 | 
                   // Note price was converted from a numeric string to a number
  | 
        
        
            | 
            | 
           206 | 
                   // response.results[0] looks like { fruit: "BANANA", price: 1.96 }
  | 
        
        
            | 
            | 
           207 | 
              | 
        
        
            | 
            | 
           208 | 
               @method apply
  | 
        
        
            | 
            | 
           209 | 
               @param {Object} [schema] Schema to apply.  Supported configuration
  | 
        
        
            | 
            | 
           210 | 
                   properties are:
  | 
        
        
            | 
            | 
           211 | 
                 @param {String} [schema.resultListLocator] Path locator for the
  | 
        
        
            | 
            | 
           212 | 
                     location of the array of records to flatten into `response.results`
  | 
        
        
            | 
            | 
           213 | 
                 @param {Array} [schema.resultFields] Field identifiers to
  | 
        
        
            | 
            | 
           214 | 
                     locate/assign values in the response records. See above for
  | 
        
        
            | 
            | 
           215 | 
                     details.
  | 
        
        
            | 
            | 
           216 | 
                 @param {Array} [schema.metaFields] Path locators to extract extra
  | 
        
        
            | 
            | 
           217 | 
                     non-record related information from the data object.
  | 
        
        
            | 
            | 
           218 | 
               @param {Object|Array|String} data JSON data or its string serialization.
  | 
        
        
            | 
            | 
           219 | 
               @return {Object} An Object with properties `results` and `meta`
  | 
        
        
            | 
            | 
           220 | 
               @static
  | 
        
        
            | 
            | 
           221 | 
               **/
  | 
        
        
            | 
            | 
           222 | 
               apply: function(schema, data) {
  | 
        
        
            | 
            | 
           223 | 
                   var data_in = data,
  | 
        
        
            | 
            | 
           224 | 
                       data_out = { results: [], meta: {} };
  | 
        
        
            | 
            | 
           225 | 
              | 
        
        
            | 
            | 
           226 | 
                   // Convert incoming JSON strings
  | 
        
        
            | 
            | 
           227 | 
                   if (!isObject(data)) {
  | 
        
        
            | 
            | 
           228 | 
                       try {
  | 
        
        
            | 
            | 
           229 | 
                           data_in = Y.JSON.parse(data);
  | 
        
        
            | 
            | 
           230 | 
                       }
  | 
        
        
            | 
            | 
           231 | 
                       catch(e) {
  | 
        
        
            | 
            | 
           232 | 
                           data_out.error = e;
  | 
        
        
            | 
            | 
           233 | 
                           return data_out;
  | 
        
        
            | 
            | 
           234 | 
                       }
  | 
        
        
            | 
            | 
           235 | 
                   }
  | 
        
        
            | 
            | 
           236 | 
              | 
        
        
            | 
            | 
           237 | 
                   if (isObject(data_in) && schema) {
  | 
        
        
            | 
            | 
           238 | 
                       // Parse results data
  | 
        
        
            | 
            | 
           239 | 
                       data_out = SchemaJSON._parseResults.call(this, schema, data_in, data_out);
  | 
        
        
            | 
            | 
           240 | 
              | 
        
        
            | 
            | 
           241 | 
                       // Parse meta data
  | 
        
        
            | 
            | 
           242 | 
                       if (schema.metaFields !== undefined) {
  | 
        
        
            | 
            | 
           243 | 
                           data_out = SchemaJSON._parseMeta(schema.metaFields, data_in, data_out);
  | 
        
        
            | 
            | 
           244 | 
                       }
  | 
        
        
            | 
            | 
           245 | 
                   }
  | 
        
        
            | 
            | 
           246 | 
                   else {
  | 
        
        
            | 
            | 
           247 | 
                       Y.log("JSON data could not be schema-parsed: " + Y.dump(data) + " " + Y.dump(data), "error", "dataschema-json");
  | 
        
        
            | 
            | 
           248 | 
                       data_out.error = new Error("JSON schema parse failure");
  | 
        
        
            | 
            | 
           249 | 
                   }
  | 
        
        
            | 
            | 
           250 | 
              | 
        
        
            | 
            | 
           251 | 
                   return data_out;
  | 
        
        
            | 
            | 
           252 | 
               },
  | 
        
        
            | 
            | 
           253 | 
              | 
        
        
            | 
            | 
           254 | 
               /**
  | 
        
        
            | 
            | 
           255 | 
                * Schema-parsed list of results from full data
  | 
        
        
            | 
            | 
           256 | 
                *
  | 
        
        
            | 
            | 
           257 | 
                * @method _parseResults
  | 
        
        
            | 
            | 
           258 | 
                * @param schema {Object} Schema to parse against.
  | 
        
        
            | 
            | 
           259 | 
                * @param json_in {Object} JSON to parse.
  | 
        
        
            | 
            | 
           260 | 
                * @param data_out {Object} In-progress parsed data to update.
  | 
        
        
            | 
            | 
           261 | 
                * @return {Object} Parsed data object.
  | 
        
        
            | 
            | 
           262 | 
                * @static
  | 
        
        
            | 
            | 
           263 | 
                * @protected
  | 
        
        
            | 
            | 
           264 | 
                */
  | 
        
        
            | 
            | 
           265 | 
               _parseResults: function(schema, json_in, data_out) {
  | 
        
        
            | 
            | 
           266 | 
                   var getPath  = SchemaJSON.getPath,
  | 
        
        
            | 
            | 
           267 | 
                       getValue = SchemaJSON.getLocationValue,
  | 
        
        
            | 
            | 
           268 | 
                       path     = getPath(schema.resultListLocator),
  | 
        
        
            | 
            | 
           269 | 
                       results  = path ?
  | 
        
        
            | 
            | 
           270 | 
                                   (getValue(path, json_in) ||
  | 
        
        
            | 
            | 
           271 | 
                                    // Fall back to treat resultListLocator as a simple key
  | 
        
        
            | 
            | 
           272 | 
                                       json_in[schema.resultListLocator]) :
  | 
        
        
            | 
            | 
           273 | 
                                   // Or if no resultListLocator is supplied, use the input
  | 
        
        
            | 
            | 
           274 | 
                                   json_in;
  | 
        
        
            | 
            | 
           275 | 
              | 
        
        
            | 
            | 
           276 | 
                   if (isArray(results)) {
  | 
        
        
            | 
            | 
           277 | 
                       // if no result fields are passed in, then just take
  | 
        
        
            | 
            | 
           278 | 
                       // the results array whole-hog Sometimes you're getting
  | 
        
        
            | 
            | 
           279 | 
                       // an array of strings, or want the whole object, so
  | 
        
        
            | 
            | 
           280 | 
                       // resultFields don't make sense.
  | 
        
        
            | 
            | 
           281 | 
                       if (isArray(schema.resultFields)) {
  | 
        
        
            | 
            | 
           282 | 
                           data_out = SchemaJSON._getFieldValues.call(this, schema.resultFields, results, data_out);
  | 
        
        
            | 
            | 
           283 | 
                       } else {
  | 
        
        
            | 
            | 
           284 | 
                           data_out.results = results;
  | 
        
        
            | 
            | 
           285 | 
                       }
  | 
        
        
            | 
            | 
           286 | 
                   } else if (schema.resultListLocator) {
  | 
        
        
            | 
            | 
           287 | 
                       data_out.results = [];
  | 
        
        
            | 
            | 
           288 | 
                       data_out.error = new Error("JSON results retrieval failure");
  | 
        
        
            | 
            | 
           289 | 
                       Y.log("JSON data could not be parsed: " + Y.dump(json_in), "error", "dataschema-json");
  | 
        
        
            | 
            | 
           290 | 
                   }
  | 
        
        
            | 
            | 
           291 | 
              | 
        
        
            | 
            | 
           292 | 
                   return data_out;
  | 
        
        
            | 
            | 
           293 | 
               },
  | 
        
        
            | 
            | 
           294 | 
              | 
        
        
            | 
            | 
           295 | 
               /**
  | 
        
        
            | 
            | 
           296 | 
                * Get field data values out of list of full results
  | 
        
        
            | 
            | 
           297 | 
                *
  | 
        
        
            | 
            | 
           298 | 
                * @method _getFieldValues
  | 
        
        
            | 
            | 
           299 | 
                * @param fields {Array} Fields to find.
  | 
        
        
            | 
            | 
           300 | 
                * @param array_in {Array} Results to parse.
  | 
        
        
            | 
            | 
           301 | 
                * @param data_out {Object} In-progress parsed data to update.
  | 
        
        
            | 
            | 
           302 | 
                * @return {Object} Parsed data object.
  | 
        
        
            | 
            | 
           303 | 
                * @static
  | 
        
        
            | 
            | 
           304 | 
                * @protected
  | 
        
        
            | 
            | 
           305 | 
                */
  | 
        
        
            | 
            | 
           306 | 
               _getFieldValues: function(fields, array_in, data_out) {
  | 
        
        
            | 
            | 
           307 | 
                   var results = [],
  | 
        
        
            | 
            | 
           308 | 
                       len = fields.length,
  | 
        
        
            | 
            | 
           309 | 
                       i, j,
  | 
        
        
            | 
            | 
           310 | 
                       field, key, locator, path, parser, val,
  | 
        
        
            | 
            | 
           311 | 
                       simplePaths = [], complexPaths = [], fieldParsers = [],
  | 
        
        
            | 
            | 
           312 | 
                       result, record;
  | 
        
        
            | 
            | 
           313 | 
              | 
        
        
            | 
            | 
           314 | 
                   // First collect hashes of simple paths, complex paths, and parsers
  | 
        
        
            | 
            | 
           315 | 
                   for (i=0; i<len; i++) {
  | 
        
        
            | 
            | 
           316 | 
                       field = fields[i]; // A field can be a simple string or a hash
  | 
        
        
            | 
            | 
           317 | 
                       key = field.key || field; // Find the key
  | 
        
        
            | 
            | 
           318 | 
                       locator = field.locator || key; // Find the locator
  | 
        
        
            | 
            | 
           319 | 
              | 
        
        
            | 
            | 
           320 | 
                       // Validate and store locators for later
  | 
        
        
            | 
            | 
           321 | 
                       path = SchemaJSON.getPath(locator);
  | 
        
        
            | 
            | 
           322 | 
                       if (path) {
  | 
        
        
            | 
            | 
           323 | 
                           if (path.length === 1) {
  | 
        
        
            | 
            | 
           324 | 
                               simplePaths.push({
  | 
        
        
            | 
            | 
           325 | 
                                   key : key,
  | 
        
        
            | 
            | 
           326 | 
                                   path: path[0]
  | 
        
        
            | 
            | 
           327 | 
                               });
  | 
        
        
            | 
            | 
           328 | 
                           } else {
  | 
        
        
            | 
            | 
           329 | 
                               complexPaths.push({
  | 
        
        
            | 
            | 
           330 | 
                                   key    : key,
  | 
        
        
            | 
            | 
           331 | 
                                   path   : path,
  | 
        
        
            | 
            | 
           332 | 
                                   locator: locator
  | 
        
        
            | 
            | 
           333 | 
                               });
  | 
        
        
            | 
            | 
           334 | 
                           }
  | 
        
        
            | 
            | 
           335 | 
                       } else {
  | 
        
        
            | 
            | 
           336 | 
                           Y.log("Invalid key syntax: " + key, "warn", "dataschema-json");
  | 
        
        
            | 
            | 
           337 | 
                       }
  | 
        
        
            | 
            | 
           338 | 
              | 
        
        
            | 
            | 
           339 | 
                       // Validate and store parsers for later
  | 
        
        
            | 
            | 
           340 | 
                       //TODO: use Y.DataSchema.parse?
  | 
        
        
            | 
            | 
           341 | 
                       parser = (isFunction(field.parser)) ?
  | 
        
        
            | 
            | 
           342 | 
                                   field.parser :
  | 
        
        
            | 
            | 
           343 | 
                                   Y.Parsers[field.parser + ''];
  | 
        
        
            | 
            | 
           344 | 
              | 
        
        
            | 
            | 
           345 | 
                       if (parser) {
  | 
        
        
            | 
            | 
           346 | 
                           fieldParsers.push({
  | 
        
        
            | 
            | 
           347 | 
                               key   : key,
  | 
        
        
            | 
            | 
           348 | 
                               parser: parser
  | 
        
        
            | 
            | 
           349 | 
                           });
  | 
        
        
            | 
            | 
           350 | 
                       }
  | 
        
        
            | 
            | 
           351 | 
                   }
  | 
        
        
            | 
            | 
           352 | 
              | 
        
        
            | 
            | 
           353 | 
                   // Traverse list of array_in, creating records of simple fields,
  | 
        
        
            | 
            | 
           354 | 
                   // complex fields, and applying parsers as necessary
  | 
        
        
            | 
            | 
           355 | 
                   for (i=array_in.length-1; i>=0; --i) {
  | 
        
        
            | 
            | 
           356 | 
                       record = {};
  | 
        
        
            | 
            | 
           357 | 
                       result = array_in[i];
  | 
        
        
            | 
            | 
           358 | 
                       if(result) {
  | 
        
        
            | 
            | 
           359 | 
                           // Cycle through complexLocators
  | 
        
        
            | 
            | 
           360 | 
                           for (j=complexPaths.length - 1; j>=0; --j) {
  | 
        
        
            | 
            | 
           361 | 
                               path = complexPaths[j];
  | 
        
        
            | 
            | 
           362 | 
                               val = SchemaJSON.getLocationValue(path.path, result);
  | 
        
        
            | 
            | 
           363 | 
                               if (val === undefined) {
  | 
        
        
            | 
            | 
           364 | 
                                   val = SchemaJSON.getLocationValue([path.locator], result);
  | 
        
        
            | 
            | 
           365 | 
                                   // Fail over keys like "foo.bar" from nested parsing
  | 
        
        
            | 
            | 
           366 | 
                                   // to single token parsing if a value is found in
  | 
        
        
            | 
            | 
           367 | 
                                   // results["foo.bar"]
  | 
        
        
            | 
            | 
           368 | 
                                   if (val !== undefined) {
  | 
        
        
            | 
            | 
           369 | 
                                       simplePaths.push({
  | 
        
        
            | 
            | 
           370 | 
                                           key:  path.key,
  | 
        
        
            | 
            | 
           371 | 
                                           path: path.locator
  | 
        
        
            | 
            | 
           372 | 
                                       });
  | 
        
        
            | 
            | 
           373 | 
                                       // Don't try to process the path as complex
  | 
        
        
            | 
            | 
           374 | 
                                       // for further results
  | 
        
        
            | 
            | 
           375 | 
                                       complexPaths.splice(i,1);
  | 
        
        
            | 
            | 
           376 | 
                                       continue;
  | 
        
        
            | 
            | 
           377 | 
                                   }
  | 
        
        
            | 
            | 
           378 | 
                               }
  | 
        
        
            | 
            | 
           379 | 
              | 
        
        
            | 
            | 
           380 | 
                               record[path.key] = Base.parse.call(this,
  | 
        
        
            | 
            | 
           381 | 
                                   (SchemaJSON.getLocationValue(path.path, result)), path);
  | 
        
        
            | 
            | 
           382 | 
                           }
  | 
        
        
            | 
            | 
           383 | 
              | 
        
        
            | 
            | 
           384 | 
                           // Cycle through simpleLocators
  | 
        
        
            | 
            | 
           385 | 
                           for (j = simplePaths.length - 1; j >= 0; --j) {
  | 
        
        
            | 
            | 
           386 | 
                               path = simplePaths[j];
  | 
        
        
            | 
            | 
           387 | 
                               // Bug 1777850: The result might be an array instead of object
  | 
        
        
            | 
            | 
           388 | 
                               record[path.key] = Base.parse.call(this,
  | 
        
        
            | 
            | 
           389 | 
                                       ((result[path.path] === undefined) ?
  | 
        
        
            | 
            | 
           390 | 
                                       result[j] : result[path.path]), path);
  | 
        
        
            | 
            | 
           391 | 
                           }
  | 
        
        
            | 
            | 
           392 | 
              | 
        
        
            | 
            | 
           393 | 
                           // Cycle through fieldParsers
  | 
        
        
            | 
            | 
           394 | 
                           for (j=fieldParsers.length-1; j>=0; --j) {
  | 
        
        
            | 
            | 
           395 | 
                               key = fieldParsers[j].key;
  | 
        
        
            | 
            | 
           396 | 
                               record[key] = fieldParsers[j].parser.call(this, record[key]);
  | 
        
        
            | 
            | 
           397 | 
                               // Safety net
  | 
        
        
            | 
            | 
           398 | 
                               if (record[key] === undefined) {
  | 
        
        
            | 
            | 
           399 | 
                                   record[key] = null;
  | 
        
        
            | 
            | 
           400 | 
                               }
  | 
        
        
            | 
            | 
           401 | 
                           }
  | 
        
        
            | 
            | 
           402 | 
                           results[i] = record;
  | 
        
        
            | 
            | 
           403 | 
                       }
  | 
        
        
            | 
            | 
           404 | 
                   }
  | 
        
        
            | 
            | 
           405 | 
                   data_out.results = results;
  | 
        
        
            | 
            | 
           406 | 
                   return data_out;
  | 
        
        
            | 
            | 
           407 | 
               },
  | 
        
        
            | 
            | 
           408 | 
              | 
        
        
            | 
            | 
           409 | 
               /**
  | 
        
        
            | 
            | 
           410 | 
                * Parses results data according to schema
  | 
        
        
            | 
            | 
           411 | 
                *
  | 
        
        
            | 
            | 
           412 | 
                * @method _parseMeta
  | 
        
        
            | 
            | 
           413 | 
                * @param metaFields {Object} Metafields definitions.
  | 
        
        
            | 
            | 
           414 | 
                * @param json_in {Object} JSON to parse.
  | 
        
        
            | 
            | 
           415 | 
                * @param data_out {Object} In-progress parsed data to update.
  | 
        
        
            | 
            | 
           416 | 
                * @return {Object} Schema-parsed meta data.
  | 
        
        
            | 
            | 
           417 | 
                * @static
  | 
        
        
            | 
            | 
           418 | 
                * @protected
  | 
        
        
            | 
            | 
           419 | 
                */
  | 
        
        
            | 
            | 
           420 | 
               _parseMeta: function(metaFields, json_in, data_out) {
  | 
        
        
            | 
            | 
           421 | 
                   if (isObject(metaFields)) {
  | 
        
        
            | 
            | 
           422 | 
                       var key, path;
  | 
        
        
            | 
            | 
           423 | 
                       for(key in metaFields) {
  | 
        
        
            | 
            | 
           424 | 
                           if (metaFields.hasOwnProperty(key)) {
  | 
        
        
            | 
            | 
           425 | 
                               path = SchemaJSON.getPath(metaFields[key]);
  | 
        
        
            | 
            | 
           426 | 
                               if (path && json_in) {
  | 
        
        
            | 
            | 
           427 | 
                                   data_out.meta[key] = SchemaJSON.getLocationValue(path, json_in);
  | 
        
        
            | 
            | 
           428 | 
                               }
  | 
        
        
            | 
            | 
           429 | 
                           }
  | 
        
        
            | 
            | 
           430 | 
                       }
  | 
        
        
            | 
            | 
           431 | 
                   }
  | 
        
        
            | 
            | 
           432 | 
                   else {
  | 
        
        
            | 
            | 
           433 | 
                       data_out.error = new Error("JSON meta data retrieval failure");
  | 
        
        
            | 
            | 
           434 | 
                   }
  | 
        
        
            | 
            | 
           435 | 
                   return data_out;
  | 
        
        
            | 
            | 
           436 | 
               }
  | 
        
        
            | 
            | 
           437 | 
           };
  | 
        
        
            | 
            | 
           438 | 
              | 
        
        
            | 
            | 
           439 | 
           // TODO: Y.Object + mix() might be better here
  | 
        
        
            | 
            | 
           440 | 
           Y.DataSchema.JSON = Y.mix(SchemaJSON, Base);
  | 
        
        
            | 
            | 
           441 | 
              | 
        
        
            | 
            | 
           442 | 
              | 
        
        
            | 
            | 
           443 | 
           }, '3.18.1', {"requires": ["dataschema-base", "json"]});
  |