dataschema.js revision 0d6d1a2d994933a68a100ec3dcdc7c7a0eeeae6c
0N/A * The DataSchema utility provides a common configurable interface for widgets to 0N/A * apply a given schema to a variety of data. 0N/A * Base class for the YUI DataSchema utility. 0N/A * @class DataSchema.Base 0N/A * Returns string name. 0N/A * @return {String} String representation for this object. 0N/A * Overridable method returns data as-is. 0N/A * @param schema {Object} Schema to apply. 0N/A * @param data {Object} Data. 0N/A * @return {Object} Schema-parsed data. 0N/A * The DataSchema utility provides a common configurable interface for widgets to 0N/A * apply a given schema to a variety of data. 0N/A * @module dataschema 2963N/A * JSON subclass for the YUI DataSchema utility. 2963N/A ///////////////////////////////////////////////////////////////////////////// 2963N/A ///////////////////////////////////////////////////////////////////////////// 3090N/A * @return {String} String representation for this object. 2963N/A * Utility function converts JSON locator strings into walkable paths 2963N/A * @param locator {String} JSON value locator. 2963N/A * @return {String[]} Walkable path to data value. 2963N/A // Strip the ["string keys"] and [1] array indexes 2963N/A function (x,$1,$2) {keys[i]=$2;return '.@
'+(i++);}). 2963N/A function (x,$1) {keys[i]=parseInt($1,10)|0;return '.@
'+(i++);}). 2963N/A replace(/^\./,''); // remove leading dot 2963N/A // Validate against problematic characters. 2963N/A if (!/[^\w\.\$@]/.test(locator)) { 2963N/A for (i=path.length-1; i >= 0; --i) { 2963N/A if (path[i].charAt(0) === '@
') { 2963N/A path[i] = keys[parseInt(path[i].substr(1),10)]; 2963N/A * Utility function to walk a path and return the value located there. 2963N/A * @param path {String[]} Locator path. 2963N/A * @param data {String} Data to traverse. 2963N/A * @return {Object} Data value at location. 2963N/A getLocationValue: function (path, data) { 2963N/A * Applies a given schema to given JSON data. 2963N/A * @param schema {Object} Schema to apply. 2963N/A * @param data {Object} JSON data. 2963N/A * @return {Object} Schema-parsed data. 0N/A apply: function(schema, data) { 0N/A data_out = {results:[],meta:{}}; 0N/A // Convert incoming JSON strings 0N/A if(!LANG.isObject(data)) { 0N/A if(LANG.isObject(data_in) && schema) { 0N/A // Parse results data 0N/A if(!LANG.isUndefined(schema.resultsLocator)) { 0N/A data_out = SchemaJSON._parseResults(schema, data_in, data_out); 0N/A if(!LANG.isUndefined(schema.metaFields)) { 0N/A data_out = SchemaJSON._parseMeta(schema.metaFields, data_in, data_out); 0N/A data_out.error = true; 0N/A * Schema-parsed list of results from full data 0N/A * @method _parseResults 0N/A * @param schema {Object} Schema to parse against. 2581N/A * @param data_in {Object} Data to parse. 2581N/A * @param data_out {Object} In-progress parsed data to update. 2581N/A * @return {Object} Parsed data object. 2581N/A _parseResults: function(schema, data_in, data_out) { 0N/A if(schema.resultsLocator) { 517N/A path = SchemaJSON.buildPath(schema.resultsLocator); 0N/A results = SchemaJSON.getLocationValue(path, data_in); 0N/A if (results === undefined) { 0N/A data_out.results = []; 0N/A error = new Error(this.toString() + " Results retrieval failure"); 0N/A if(LANG.isArray(schema.resultsFields) && LANG.isArray(results)) { 0N/A data_out = SchemaJSON._getFieldValues(schema.resultsFields, results, data_out); 4680N/A error = new Error(this.toString() + " Fields retrieval failure"); 0N/A error = new Error(this.toString() + " Results locator failure"); 0N/A * Get field data values out of list of full results 0N/A * @method _getFieldValues 2963N/A * @param fields {Array} Fields to find. 2963N/A * @param data_in {Array} Results data to parse. 2963N/A * @param data_out {Object} In-progress parsed data to update. 2963N/A * @return {Object} Parsed data object. 2963N/A _getFieldValues: function(fields, data_in, data_out) { 2963N/A simplePaths = [], complexPaths = [], fieldParsers = [], 2963N/A // First collect hashes of simple paths, complex paths, and parsers 2963N/A field = fields[i]; // A field can be a simple string or a hash 2963N/A key = field.key || field; // Find the key 2963N/A // Validate and store locators for later 2963N/A path = SchemaJSON.buildPath(key); 0N/A simplePaths[simplePaths.length] = {key:key, path:path[0]}; 1365N/A complexPaths[complexPaths.length] = {key:key, path:path}; 1365N/A // Validate and store parsers for later 1365N/A //TODO: implement shortcuts 1365N/A parser = (LANG.isFunction(field.parser)) ? field.parser : Y.DataSchema[field.parser+'']; 1365N/A fieldParsers[fieldParsers.length] = {key:key, parser:parser}; 1365N/A // Traverse list of data_in, creating records of simple fields, 2324N/A // complex fields, and applying parsers as necessary 2324N/A for (i=data_in.length-1; i>=0; --i) { 1365N/A // Cycle through simpleLocators 1365N/A for (j=simplePaths.length-1; j>=0; --j) { 1365N/A // Bug 1777850: The result might be an array instead of object 1365N/A record[simplePaths[j].key] = 2324N/A LANG.isUndefined(result[simplePaths[j].path]) ? 2324N/A result[j] : result[simplePaths[j].path]; 1365N/A // Cycle through complexLocators 5694N/A for (j=complexPaths.length - 1; j>=0; --j) { 5694N/A record[complexPaths[j].key] = SchemaJSON.getLocationValue(complexPaths[j].path, result); 2746N/A // Cycle through fieldParsers 1365N/A for (j=fieldParsers.length-1; j>=0; --j) { 1365N/A record[key] = fieldParsers[j].parser(record[key]); 1365N/A if (LANG.isUndefined(record[key])) { 1365N/A data_out.results = results; 1365N/A * Parses results data according to schema 0N/A * @method _parseMeta 0N/A * @param data_out {Object} Data to parse. 0N/A * @param data_in {Object} In-progress parsed data to update. 0N/A * @return {Object} Schema-parsed meta data. 0N/A _parseMeta: function(metaFields, data_in, data_out) { 0N/A if(LANG.isObject(metaFields)) { 0N/A if (metaFields.hasOwnProperty(key)) { 2581N/A path = SchemaJSON.buildPath(metaFields[key]); 0N/A data_out.meta[key] = SchemaJSON.getLocationValue(path, data_in); 2581N/A data_out.error = new Error(this.toString() + " Meta retrieval failure"); 0N/A * The DataSchema utility provides a common configurable interface for widgets to 0N/A * apply a given schema to a variety of data. 0N/A * @module dataschema 0N/A * XML subclass for the YUI DataSchema utility. 0N/A * @extends DataSchema.Base 5694N/A ///////////////////////////////////////////////////////////////////////////// 0N/A ///////////////////////////////////////////////////////////////////////////// 0N/A * Returns string name. 0N/A * @return {String} String representation for this object. 0N/A toString: function() { 0N/A * Applies a given schema to given XML data. 0N/A * @param schema {Object} Schema to apply. 0N/A * @param data {XMLDoc} XML document. 0N/A * @return {Object} Schema-parsed data. 795N/A apply: function(schema, data) { 1365N/A data_out = {results:[],meta:{}}; 0N/A if(LANG.isObject(data_in) && schema) { 0N/A // Parse results data 517N/A if(!LANG.isUndefined(schema.resultsLocator)) { 0N/A data_out = SchemaXML._parseResults(schema, data_in, data_out); 0N/A if(!LANG.isUndefined(schema.metaFields)) { 0N/A data_out = SchemaXML._parseMeta(schema.metaFields, data_in, data_out); 0N/A * Schema-parsed list of results from full data 0N/A * @method _parseResults 0N/A * @param schema {Object} Schema to parse against. 0N/A * @param data_in {Object} Data to parse. 0N/A * @param data_out {Object} In-progress parsed data to update. 0N/A * @return {Object} Parsed data object. 0N/A _parseResults: function(schema, data_in, data_out) { 0N/A if(schema.resultsLocator) { 0N/A nodeList = data_in.getElementsByTagName(schema.resultsLocator); 0N/A if(LANG.isArray(schema.resultsFields) && nodeList.length) { 0N/A data_out = SchemaXML._getFieldValues(schema.resultsFields, nodeList, data_out); 0N/A data_out.results = []; 0N/A data_out.error = new Error(this.toString() + " Fields retrieval failure"); 0N/A //error = new Error(this.toString() + " Results locator failure"); 0N/A //data_out.error = error; 0N/A * Get field data values out of nodelist of full results 0N/A * @method _getFieldValues 0N/A * @param fields {Array} Fields to find. 0N/A * @param data_in {Array} Results data to parse. 0N/A * @param data_out {Object} In-progress parsed data to update. 0N/A * @return {Object} Parsed data object. 0N/A _getFieldValues: function(fields, data_in, data_out) { 0N/A i = data_in.length-1, 0N/A item, result_in, result_out, field, key, data, subnode, datapieces; 0N/A // Loop through each result node 0N/A result_in = data_in[i]; 517N/A // Find each field value 0N/A j = fields.length-1; 0N/A key = (LANG.isValue(field.key)) ? field.key : field; 517N/A // Values may be held in an attribute... 0N/A if(result_in.attributes.getNamedItem(key)) { 0N/A data = result_in.attributes.getNamedItem(key).value; 0N/A subnode = result_in.getElementsByTagName(key); 0N/A if(subnode && subnode.item(0)) { 517N/A item = subnode.item(0); 0N/A // For IE, then DOM... 0N/A data = (item) ? ((item.text) ? item.text : (item.textContent) ? item.textContent : null) : null; 0N/A // ...then fallback, but check for multiple child nodes 517N/A for(var k=0, len=item.childNodes.length; k<len; k++) { 0N/A if(item.childNodes[k].nodeValue) { 0N/A datapieces[datapieces.length] = item.childNodes[k].nodeValue; 0N/A if(datapieces.length > 0) { 0N/A data = datapieces.join(""); 0N/A var parser = (typeof field.parser === 'function') ? 0N/A // TODO: implement shortcuts 0N/A null;//DS.Parser[field.parser+'']; 0N/A data = parser.call(this, data); 0N/A if(data === undefined) { 0N/A result_out[key] = data; 0N/A results[i] = result_out; 0N/A data_out.error = new Error(this.toString() + " Fields retrieval failure"); 0N/A data_out.results = results; 0N/A * Parses results data according to schema 0N/A * @method _parseMeta 0N/A * @param data_out {Object} Data to parse. 0N/A * @param data_in {Object} In-progress parsed data to update. 0N/A * @return {Object} Schema-parsed meta data. 0N/A _parseMeta: function(metaFields, data_in, data_out) { 5694N/A if(LANG.isObject(metaFields)) { 5694N/A if (metaFields.hasOwnProperty(key)) { 5694N/A value = data_in.getElementsByTagName(path)[0]; 5694N/A value = value.firstChild.nodeValue; 5694N/A value = data_in.attributes.getNamedItem(path); 5694N/A data_out.meta[key] = value; 0N/A data_out.error = new Error(this.toString() + " Meta retrieval failure");