src/cm/media/js/lib/yui/yui3.0.0/build/dataschema/dataschema-json-debug.js
changeset 0 40c8f766c9b8
equal deleted inserted replaced
-1:000000000000 0:40c8f766c9b8
       
     1 /*
       
     2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
       
     3 Code licensed under the BSD License:
       
     4 http://developer.yahoo.net/yui/license.txt
       
     5 version: 3.0.0
       
     6 build: 1549
       
     7 */
       
     8 YUI.add('dataschema-json', function(Y) {
       
     9 
       
    10 /**
       
    11  * Provides a DataSchema implementation which can be used to work with JSON data.
       
    12  *
       
    13  * @module dataschema
       
    14  * @submodule dataschema-json
       
    15  */
       
    16 
       
    17 /**
       
    18  * JSON subclass for the DataSchema Utility.
       
    19  * @class DataSchema.JSON
       
    20  * @extends DataSchema.Base
       
    21  * @static
       
    22  */
       
    23 var LANG = Y.Lang,
       
    24 
       
    25     SchemaJSON = {
       
    26 
       
    27         /////////////////////////////////////////////////////////////////////////////
       
    28         //
       
    29         // DataSchema.JSON static methods
       
    30         //
       
    31         /////////////////////////////////////////////////////////////////////////////
       
    32         /**
       
    33          * Utility function converts JSON locator strings into walkable paths
       
    34          *
       
    35          * @method DataSchema.JSON.getPath
       
    36          * @param locator {String} JSON value locator.
       
    37          * @return {String[]} Walkable path to data value.
       
    38          * @static
       
    39          */
       
    40         getPath: function(locator) {
       
    41             var path = null,
       
    42                 keys = [],
       
    43                 i = 0;
       
    44 
       
    45             if (locator) {
       
    46                 // Strip the ["string keys"] and [1] array indexes
       
    47                 locator = locator.
       
    48                     replace(/\[(['"])(.*?)\1\]/g,
       
    49                     function (x,$1,$2) {keys[i]=$2;return '.@'+(i++);}).
       
    50                     replace(/\[(\d+)\]/g,
       
    51                     function (x,$1) {keys[i]=parseInt($1,10)|0;return '.@'+(i++);}).
       
    52                     replace(/^\./,''); // remove leading dot
       
    53 
       
    54                 // Validate against problematic characters.
       
    55                 if (!/[^\w\.\$@]/.test(locator)) {
       
    56                     path = locator.split('.');
       
    57                     for (i=path.length-1; i >= 0; --i) {
       
    58                         if (path[i].charAt(0) === '@') {
       
    59                             path[i] = keys[parseInt(path[i].substr(1),10)];
       
    60                         }
       
    61                     }
       
    62                 }
       
    63                 else {
       
    64                     Y.log("Invalid locator: " + locator, "error", "dataschema-json");
       
    65                 }
       
    66             }
       
    67             return path;
       
    68         },
       
    69 
       
    70         /**
       
    71          * Utility function to walk a path and return the value located there.
       
    72          *
       
    73          * @method DataSchema.JSON.getLocationValue
       
    74          * @param path {String[]} Locator path.
       
    75          * @param data {String} Data to traverse.
       
    76          * @return {Object} Data value at location.
       
    77          * @static
       
    78          */
       
    79         getLocationValue: function (path, data) {
       
    80             var i = 0,
       
    81                 len = path.length;
       
    82             for (;i<len;i++) {
       
    83                 if(!LANG.isUndefined(data[path[i]])) {
       
    84                     data = data[path[i]];
       
    85                 }
       
    86                 else {
       
    87                     data = undefined;
       
    88                     break;
       
    89                 }
       
    90             }
       
    91             return data;
       
    92         },
       
    93 
       
    94         /**
       
    95          * Applies a given schema to given JSON data.
       
    96          *
       
    97          * @method apply
       
    98          * @param schema {Object} Schema to apply.
       
    99          * @param data {Object} JSON data.
       
   100          * @return {Object} Schema-parsed data.
       
   101          * @static
       
   102          */
       
   103         apply: function(schema, data) {
       
   104             var data_in = data,
       
   105                 data_out = {results:[],meta:{}};
       
   106 
       
   107             // Convert incoming JSON strings
       
   108             if(!LANG.isObject(data)) {
       
   109                 try {
       
   110                     data_in = Y.JSON.parse(data);
       
   111                 }
       
   112                 catch(e) {
       
   113                     data_out.error = e;
       
   114                     return data_out;
       
   115                 }
       
   116             }
       
   117 
       
   118             if(LANG.isObject(data_in) && schema) {
       
   119                 // Parse results data
       
   120                 if(!LANG.isUndefined(schema.resultListLocator)) {
       
   121                     data_out = SchemaJSON._parseResults(schema, data_in, data_out);
       
   122                 }
       
   123 
       
   124                 // Parse meta data
       
   125                 if(!LANG.isUndefined(schema.metaFields)) {
       
   126                     data_out = SchemaJSON._parseMeta(schema.metaFields, data_in, data_out);
       
   127                 }
       
   128             }
       
   129             else {
       
   130                 Y.log("JSON data could not be schema-parsed: " + Y.dump(data) + " " + Y.dump(data), "error", "dataschema-json");
       
   131                 data_out.error = new Error("JSON schema parse failure");
       
   132             }
       
   133 
       
   134             return data_out;
       
   135         },
       
   136 
       
   137         /**
       
   138          * Schema-parsed list of results from full data
       
   139          *
       
   140          * @method _parseResults
       
   141          * @param schema {Object} Schema to parse against.
       
   142          * @param json_in {Object} JSON to parse.
       
   143          * @param data_out {Object} In-progress parsed data to update.
       
   144          * @return {Object} Parsed data object.
       
   145          * @static
       
   146          * @protected
       
   147          */
       
   148         _parseResults: function(schema, json_in, data_out) {
       
   149             var results = [],
       
   150                 path,
       
   151                 error;
       
   152 
       
   153             if(schema.resultListLocator) {
       
   154                 path = SchemaJSON.getPath(schema.resultListLocator);
       
   155                 if(path) {
       
   156                     results = SchemaJSON.getLocationValue(path, json_in);
       
   157                     if (results === undefined) {
       
   158                         data_out.results = [];
       
   159                         error = new Error("JSON results retrieval failure");
       
   160                     }
       
   161                     else {
       
   162                         if(LANG.isArray(schema.resultFields) && LANG.isArray(results)) {
       
   163                             data_out = SchemaJSON._getFieldValues(schema.resultFields, results, data_out);
       
   164                         }
       
   165                         else {
       
   166                             data_out.results = [];
       
   167                             error = new Error("JSON Schema fields retrieval failure");
       
   168                         }
       
   169                     }
       
   170                 }
       
   171                 else {
       
   172                     error = new Error("JSON Schema results locator failure");
       
   173                 }
       
   174 
       
   175                 if (error) {
       
   176                     Y.log("JSON data could not be parsed: " + Y.dump(json_in), "error", "dataschema-json");
       
   177                     data_out.error = error;
       
   178                 }
       
   179 
       
   180             }
       
   181             return data_out;
       
   182         },
       
   183 
       
   184         /**
       
   185          * Get field data values out of list of full results
       
   186          *
       
   187          * @method _getFieldValues
       
   188          * @param fields {Array} Fields to find.
       
   189          * @param array_in {Array} Results to parse.
       
   190          * @param data_out {Object} In-progress parsed data to update.
       
   191          * @return {Object} Parsed data object.
       
   192          * @static
       
   193          * @protected
       
   194          */
       
   195         _getFieldValues: function(fields, array_in, data_out) {
       
   196             var results = [],
       
   197                 len = fields.length,
       
   198                 i, j,
       
   199                 field, key, path, parser,
       
   200                 simplePaths = [], complexPaths = [], fieldParsers = [],
       
   201                 result, record;
       
   202 
       
   203             // First collect hashes of simple paths, complex paths, and parsers
       
   204             for (i=0; i<len; i++) {
       
   205                 field = fields[i]; // A field can be a simple string or a hash
       
   206                 key = field.key || field; // Find the key
       
   207 
       
   208                 // Validate and store locators for later
       
   209                 path = SchemaJSON.getPath(key);
       
   210                 if (path) {
       
   211                     if (path.length === 1) {
       
   212                         simplePaths[simplePaths.length] = {key:key, path:path[0]};
       
   213                     } else {
       
   214                         complexPaths[complexPaths.length] = {key:key, path:path};
       
   215                     }
       
   216                 } else {
       
   217                     Y.log("Invalid key syntax: " + key, "warn", "dataschema-json");
       
   218                 }
       
   219 
       
   220                 // Validate and store parsers for later
       
   221                 //TODO: use Y.DataSchema.parse?
       
   222                 parser = (LANG.isFunction(field.parser)) ? field.parser : Y.Parsers[field.parser+''];
       
   223                 if (parser) {
       
   224                     fieldParsers[fieldParsers.length] = {key:key, parser:parser};
       
   225                 }
       
   226             }
       
   227 
       
   228             // Traverse list of array_in, creating records of simple fields,
       
   229             // complex fields, and applying parsers as necessary
       
   230             for (i=array_in.length-1; i>=0; --i) {
       
   231                 record = {};
       
   232                 result = array_in[i];
       
   233                 if(result) {
       
   234                     // Cycle through simpleLocators
       
   235                     for (j=simplePaths.length-1; j>=0; --j) {
       
   236                         // Bug 1777850: The result might be an array instead of object
       
   237                         record[simplePaths[j].key] = Y.DataSchema.Base.parse(
       
   238                                 (LANG.isUndefined(result[simplePaths[j].path]) ?
       
   239                                 result[j] : result[simplePaths[j].path]), simplePaths[j]);
       
   240                     }
       
   241 
       
   242                     // Cycle through complexLocators
       
   243                     for (j=complexPaths.length - 1; j>=0; --j) {
       
   244                         record[complexPaths[j].key] = Y.DataSchema.Base.parse(
       
   245                             (SchemaJSON.getLocationValue(complexPaths[j].path, result)), complexPaths[j] );
       
   246                     }
       
   247 
       
   248                     // Cycle through fieldParsers
       
   249                     for (j=fieldParsers.length-1; j>=0; --j) {
       
   250                         key = fieldParsers[j].key;
       
   251                         record[key] = fieldParsers[j].parser(record[key]);
       
   252                         // Safety net
       
   253                         if (LANG.isUndefined(record[key])) {
       
   254                             record[key] = null;
       
   255                         }
       
   256                     }
       
   257                     results[i] = record;
       
   258                 }
       
   259             }
       
   260             data_out.results = results;
       
   261             return data_out;
       
   262         },
       
   263 
       
   264         /**
       
   265          * Parses results data according to schema
       
   266          *
       
   267          * @method _parseMeta
       
   268          * @param metaFields {Object} Metafields definitions.
       
   269          * @param json_in {Object} JSON to parse.
       
   270          * @param data_out {Object} In-progress parsed data to update.
       
   271          * @return {Object} Schema-parsed meta data.
       
   272          * @static
       
   273          * @protected
       
   274          */
       
   275         _parseMeta: function(metaFields, json_in, data_out) {
       
   276             if(LANG.isObject(metaFields)) {
       
   277                 var key, path;
       
   278                 for(key in metaFields) {
       
   279                     if (metaFields.hasOwnProperty(key)) {
       
   280                         path = SchemaJSON.getPath(metaFields[key]);
       
   281                         if (path && json_in) {
       
   282                             data_out.meta[key] = SchemaJSON.getLocationValue(path, json_in);
       
   283                         }
       
   284                     }
       
   285                 }
       
   286             }
       
   287             else {
       
   288                 data_out.error = new Error("JSON meta data retrieval failure");
       
   289             }
       
   290             return data_out;
       
   291         }
       
   292     };
       
   293 
       
   294 Y.DataSchema.JSON = Y.mix(SchemaJSON, Y.DataSchema.Base);
       
   295 
       
   296 
       
   297 
       
   298 }, '3.0.0' ,{requires:['json', 'dataschema-base']});