|
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-base', function(Y) { |
|
9 |
|
10 /** |
|
11 * The DataSchema utility provides a common configurable interface for widgets to |
|
12 * apply a given schema to a variety of data. |
|
13 * |
|
14 * @module dataschema |
|
15 */ |
|
16 |
|
17 /** |
|
18 * Provides the base DataSchema implementation, which can be extended to |
|
19 * create DataSchemas for specific data formats, such XML, JSON, text and |
|
20 * arrays. |
|
21 * |
|
22 * @module dataschema |
|
23 * @submodule dataschema-base |
|
24 */ |
|
25 |
|
26 var LANG = Y.Lang, |
|
27 /** |
|
28 * Base class for the YUI DataSchema Utility. |
|
29 * @class DataSchema.Base |
|
30 * @static |
|
31 */ |
|
32 SchemaBase = { |
|
33 /** |
|
34 * Overridable method returns data as-is. |
|
35 * |
|
36 * @method apply |
|
37 * @param schema {Object} Schema to apply. |
|
38 * @param data {Object} Data. |
|
39 * @return {Object} Schema-parsed data. |
|
40 * @static |
|
41 */ |
|
42 apply: function(schema, data) { |
|
43 return data; |
|
44 }, |
|
45 |
|
46 /** |
|
47 * Applies field parser, if defined |
|
48 * |
|
49 * @method parse |
|
50 * @param value {Object} Original value. |
|
51 * @param field {Object} Field. |
|
52 * @return {Object} Type-converted value. |
|
53 */ |
|
54 parse: function(value, field) { |
|
55 if(field.parser) { |
|
56 var parser = (LANG.isFunction(field.parser)) ? |
|
57 field.parser : Y.Parsers[field.parser+'']; |
|
58 if(parser) { |
|
59 value = parser.call(this, value); |
|
60 } |
|
61 else { |
|
62 Y.log("Could not find parser for field " + Y.dump(field), "warn", "dataschema-json"); |
|
63 } |
|
64 } |
|
65 return value; |
|
66 } |
|
67 }; |
|
68 |
|
69 Y.namespace("DataSchema").Base = SchemaBase; |
|
70 Y.namespace("Parsers"); |
|
71 |
|
72 |
|
73 |
|
74 }, '3.0.0' ,{requires:['base']}); |
|
75 |
|
76 YUI.add('dataschema-json', function(Y) { |
|
77 |
|
78 /** |
|
79 * Provides a DataSchema implementation which can be used to work with JSON data. |
|
80 * |
|
81 * @module dataschema |
|
82 * @submodule dataschema-json |
|
83 */ |
|
84 |
|
85 /** |
|
86 * JSON subclass for the DataSchema Utility. |
|
87 * @class DataSchema.JSON |
|
88 * @extends DataSchema.Base |
|
89 * @static |
|
90 */ |
|
91 var LANG = Y.Lang, |
|
92 |
|
93 SchemaJSON = { |
|
94 |
|
95 ///////////////////////////////////////////////////////////////////////////// |
|
96 // |
|
97 // DataSchema.JSON static methods |
|
98 // |
|
99 ///////////////////////////////////////////////////////////////////////////// |
|
100 /** |
|
101 * Utility function converts JSON locator strings into walkable paths |
|
102 * |
|
103 * @method DataSchema.JSON.getPath |
|
104 * @param locator {String} JSON value locator. |
|
105 * @return {String[]} Walkable path to data value. |
|
106 * @static |
|
107 */ |
|
108 getPath: function(locator) { |
|
109 var path = null, |
|
110 keys = [], |
|
111 i = 0; |
|
112 |
|
113 if (locator) { |
|
114 // Strip the ["string keys"] and [1] array indexes |
|
115 locator = locator. |
|
116 replace(/\[(['"])(.*?)\1\]/g, |
|
117 function (x,$1,$2) {keys[i]=$2;return '.@'+(i++);}). |
|
118 replace(/\[(\d+)\]/g, |
|
119 function (x,$1) {keys[i]=parseInt($1,10)|0;return '.@'+(i++);}). |
|
120 replace(/^\./,''); // remove leading dot |
|
121 |
|
122 // Validate against problematic characters. |
|
123 if (!/[^\w\.\$@]/.test(locator)) { |
|
124 path = locator.split('.'); |
|
125 for (i=path.length-1; i >= 0; --i) { |
|
126 if (path[i].charAt(0) === '@') { |
|
127 path[i] = keys[parseInt(path[i].substr(1),10)]; |
|
128 } |
|
129 } |
|
130 } |
|
131 else { |
|
132 Y.log("Invalid locator: " + locator, "error", "dataschema-json"); |
|
133 } |
|
134 } |
|
135 return path; |
|
136 }, |
|
137 |
|
138 /** |
|
139 * Utility function to walk a path and return the value located there. |
|
140 * |
|
141 * @method DataSchema.JSON.getLocationValue |
|
142 * @param path {String[]} Locator path. |
|
143 * @param data {String} Data to traverse. |
|
144 * @return {Object} Data value at location. |
|
145 * @static |
|
146 */ |
|
147 getLocationValue: function (path, data) { |
|
148 var i = 0, |
|
149 len = path.length; |
|
150 for (;i<len;i++) { |
|
151 if(!LANG.isUndefined(data[path[i]])) { |
|
152 data = data[path[i]]; |
|
153 } |
|
154 else { |
|
155 data = undefined; |
|
156 break; |
|
157 } |
|
158 } |
|
159 return data; |
|
160 }, |
|
161 |
|
162 /** |
|
163 * Applies a given schema to given JSON data. |
|
164 * |
|
165 * @method apply |
|
166 * @param schema {Object} Schema to apply. |
|
167 * @param data {Object} JSON data. |
|
168 * @return {Object} Schema-parsed data. |
|
169 * @static |
|
170 */ |
|
171 apply: function(schema, data) { |
|
172 var data_in = data, |
|
173 data_out = {results:[],meta:{}}; |
|
174 |
|
175 // Convert incoming JSON strings |
|
176 if(!LANG.isObject(data)) { |
|
177 try { |
|
178 data_in = Y.JSON.parse(data); |
|
179 } |
|
180 catch(e) { |
|
181 data_out.error = e; |
|
182 return data_out; |
|
183 } |
|
184 } |
|
185 |
|
186 if(LANG.isObject(data_in) && schema) { |
|
187 // Parse results data |
|
188 if(!LANG.isUndefined(schema.resultListLocator)) { |
|
189 data_out = SchemaJSON._parseResults(schema, data_in, data_out); |
|
190 } |
|
191 |
|
192 // Parse meta data |
|
193 if(!LANG.isUndefined(schema.metaFields)) { |
|
194 data_out = SchemaJSON._parseMeta(schema.metaFields, data_in, data_out); |
|
195 } |
|
196 } |
|
197 else { |
|
198 Y.log("JSON data could not be schema-parsed: " + Y.dump(data) + " " + Y.dump(data), "error", "dataschema-json"); |
|
199 data_out.error = new Error("JSON schema parse failure"); |
|
200 } |
|
201 |
|
202 return data_out; |
|
203 }, |
|
204 |
|
205 /** |
|
206 * Schema-parsed list of results from full data |
|
207 * |
|
208 * @method _parseResults |
|
209 * @param schema {Object} Schema to parse against. |
|
210 * @param json_in {Object} JSON to parse. |
|
211 * @param data_out {Object} In-progress parsed data to update. |
|
212 * @return {Object} Parsed data object. |
|
213 * @static |
|
214 * @protected |
|
215 */ |
|
216 _parseResults: function(schema, json_in, data_out) { |
|
217 var results = [], |
|
218 path, |
|
219 error; |
|
220 |
|
221 if(schema.resultListLocator) { |
|
222 path = SchemaJSON.getPath(schema.resultListLocator); |
|
223 if(path) { |
|
224 results = SchemaJSON.getLocationValue(path, json_in); |
|
225 if (results === undefined) { |
|
226 data_out.results = []; |
|
227 error = new Error("JSON results retrieval failure"); |
|
228 } |
|
229 else { |
|
230 if(LANG.isArray(schema.resultFields) && LANG.isArray(results)) { |
|
231 data_out = SchemaJSON._getFieldValues(schema.resultFields, results, data_out); |
|
232 } |
|
233 else { |
|
234 data_out.results = []; |
|
235 error = new Error("JSON Schema fields retrieval failure"); |
|
236 } |
|
237 } |
|
238 } |
|
239 else { |
|
240 error = new Error("JSON Schema results locator failure"); |
|
241 } |
|
242 |
|
243 if (error) { |
|
244 Y.log("JSON data could not be parsed: " + Y.dump(json_in), "error", "dataschema-json"); |
|
245 data_out.error = error; |
|
246 } |
|
247 |
|
248 } |
|
249 return data_out; |
|
250 }, |
|
251 |
|
252 /** |
|
253 * Get field data values out of list of full results |
|
254 * |
|
255 * @method _getFieldValues |
|
256 * @param fields {Array} Fields to find. |
|
257 * @param array_in {Array} Results to parse. |
|
258 * @param data_out {Object} In-progress parsed data to update. |
|
259 * @return {Object} Parsed data object. |
|
260 * @static |
|
261 * @protected |
|
262 */ |
|
263 _getFieldValues: function(fields, array_in, data_out) { |
|
264 var results = [], |
|
265 len = fields.length, |
|
266 i, j, |
|
267 field, key, path, parser, |
|
268 simplePaths = [], complexPaths = [], fieldParsers = [], |
|
269 result, record; |
|
270 |
|
271 // First collect hashes of simple paths, complex paths, and parsers |
|
272 for (i=0; i<len; i++) { |
|
273 field = fields[i]; // A field can be a simple string or a hash |
|
274 key = field.key || field; // Find the key |
|
275 |
|
276 // Validate and store locators for later |
|
277 path = SchemaJSON.getPath(key); |
|
278 if (path) { |
|
279 if (path.length === 1) { |
|
280 simplePaths[simplePaths.length] = {key:key, path:path[0]}; |
|
281 } else { |
|
282 complexPaths[complexPaths.length] = {key:key, path:path}; |
|
283 } |
|
284 } else { |
|
285 Y.log("Invalid key syntax: " + key, "warn", "dataschema-json"); |
|
286 } |
|
287 |
|
288 // Validate and store parsers for later |
|
289 //TODO: use Y.DataSchema.parse? |
|
290 parser = (LANG.isFunction(field.parser)) ? field.parser : Y.Parsers[field.parser+'']; |
|
291 if (parser) { |
|
292 fieldParsers[fieldParsers.length] = {key:key, parser:parser}; |
|
293 } |
|
294 } |
|
295 |
|
296 // Traverse list of array_in, creating records of simple fields, |
|
297 // complex fields, and applying parsers as necessary |
|
298 for (i=array_in.length-1; i>=0; --i) { |
|
299 record = {}; |
|
300 result = array_in[i]; |
|
301 if(result) { |
|
302 // Cycle through simpleLocators |
|
303 for (j=simplePaths.length-1; j>=0; --j) { |
|
304 // Bug 1777850: The result might be an array instead of object |
|
305 record[simplePaths[j].key] = Y.DataSchema.Base.parse( |
|
306 (LANG.isUndefined(result[simplePaths[j].path]) ? |
|
307 result[j] : result[simplePaths[j].path]), simplePaths[j]); |
|
308 } |
|
309 |
|
310 // Cycle through complexLocators |
|
311 for (j=complexPaths.length - 1; j>=0; --j) { |
|
312 record[complexPaths[j].key] = Y.DataSchema.Base.parse( |
|
313 (SchemaJSON.getLocationValue(complexPaths[j].path, result)), complexPaths[j] ); |
|
314 } |
|
315 |
|
316 // Cycle through fieldParsers |
|
317 for (j=fieldParsers.length-1; j>=0; --j) { |
|
318 key = fieldParsers[j].key; |
|
319 record[key] = fieldParsers[j].parser(record[key]); |
|
320 // Safety net |
|
321 if (LANG.isUndefined(record[key])) { |
|
322 record[key] = null; |
|
323 } |
|
324 } |
|
325 results[i] = record; |
|
326 } |
|
327 } |
|
328 data_out.results = results; |
|
329 return data_out; |
|
330 }, |
|
331 |
|
332 /** |
|
333 * Parses results data according to schema |
|
334 * |
|
335 * @method _parseMeta |
|
336 * @param metaFields {Object} Metafields definitions. |
|
337 * @param json_in {Object} JSON to parse. |
|
338 * @param data_out {Object} In-progress parsed data to update. |
|
339 * @return {Object} Schema-parsed meta data. |
|
340 * @static |
|
341 * @protected |
|
342 */ |
|
343 _parseMeta: function(metaFields, json_in, data_out) { |
|
344 if(LANG.isObject(metaFields)) { |
|
345 var key, path; |
|
346 for(key in metaFields) { |
|
347 if (metaFields.hasOwnProperty(key)) { |
|
348 path = SchemaJSON.getPath(metaFields[key]); |
|
349 if (path && json_in) { |
|
350 data_out.meta[key] = SchemaJSON.getLocationValue(path, json_in); |
|
351 } |
|
352 } |
|
353 } |
|
354 } |
|
355 else { |
|
356 data_out.error = new Error("JSON meta data retrieval failure"); |
|
357 } |
|
358 return data_out; |
|
359 } |
|
360 }; |
|
361 |
|
362 Y.DataSchema.JSON = Y.mix(SchemaJSON, Y.DataSchema.Base); |
|
363 |
|
364 |
|
365 |
|
366 }, '3.0.0' ,{requires:['json', 'dataschema-base']}); |
|
367 |
|
368 YUI.add('dataschema-xml', function(Y) { |
|
369 |
|
370 /** |
|
371 * Provides a DataSchema implementation which can be used to work with XML data. |
|
372 * |
|
373 * @module dataschema |
|
374 * @submodule dataschema-xml |
|
375 */ |
|
376 var LANG = Y.Lang, |
|
377 |
|
378 /** |
|
379 * XML subclass for the DataSchema Utility. |
|
380 * @class DataSchema.XML |
|
381 * @extends DataSchema.Base |
|
382 * @static |
|
383 */ |
|
384 SchemaXML = { |
|
385 |
|
386 ///////////////////////////////////////////////////////////////////////////// |
|
387 // |
|
388 // DataSchema.XML static methods |
|
389 // |
|
390 ///////////////////////////////////////////////////////////////////////////// |
|
391 /** |
|
392 * Applies a given schema to given XML data. |
|
393 * |
|
394 * @method apply |
|
395 * @param schema {Object} Schema to apply. |
|
396 * @param data {XMLDoc} XML document. |
|
397 * @return {Object} Schema-parsed data. |
|
398 * @static |
|
399 */ |
|
400 apply: function(schema, data) { |
|
401 var xmldoc = data, |
|
402 data_out = {results:[],meta:{}}; |
|
403 |
|
404 if(xmldoc && xmldoc.nodeType && (xmldoc.nodeType === 9 || xmldoc.nodeType === 1 || xmldoc.nodeType === 11) && schema) { |
|
405 // Parse results data |
|
406 data_out = SchemaXML._parseResults(schema, xmldoc, data_out); |
|
407 |
|
408 // Parse meta data |
|
409 data_out = SchemaXML._parseMeta(schema.metaFields, xmldoc, data_out); |
|
410 } |
|
411 else { |
|
412 Y.log("XML data could not be schema-parsed: " + Y.dump(data) + " " + Y.dump(data), "error", "dataschema-xml"); |
|
413 data_out.error = new Error("XML schema parse failure"); |
|
414 } |
|
415 |
|
416 return data_out; |
|
417 }, |
|
418 |
|
419 /** |
|
420 * Get an XPath-specified value for a given field from an XML node or document. |
|
421 * |
|
422 * @method _getLocationValue |
|
423 * @param field {String | Object} Field definition. |
|
424 * @param context {Object} XML node or document to search within. |
|
425 * @return {Object} Data value or null. |
|
426 * @static |
|
427 * @protected |
|
428 */ |
|
429 _getLocationValue: function(field, context) { |
|
430 var locator = field.locator || field.key || field, |
|
431 xmldoc = context.ownerDocument || context, |
|
432 result, res, value = null; |
|
433 |
|
434 try { |
|
435 // Standards mode |
|
436 if(!LANG.isUndefined(xmldoc.evaluate)) { |
|
437 result = xmldoc.evaluate(locator, context, xmldoc.createNSResolver(!context.ownerDocument ? context.documentElement : context.ownerDocument.documentElement), 0, null); |
|
438 while(res = result.iterateNext()) { |
|
439 value = res.textContent; |
|
440 } |
|
441 } |
|
442 // IE mode |
|
443 else { |
|
444 xmldoc.setProperty("SelectionLanguage", "XPath"); |
|
445 result = context.selectNodes(locator)[0]; |
|
446 value = result.value || result.text || null; |
|
447 } |
|
448 return Y.DataSchema.Base.parse(value, field); |
|
449 |
|
450 } |
|
451 catch(e) { |
|
452 } |
|
453 }, |
|
454 |
|
455 /** |
|
456 * Parses results data according to schema |
|
457 * |
|
458 * @method _parseMeta |
|
459 * @param xmldoc_in {Object} XML document parse. |
|
460 * @param data_out {Object} In-progress schema-parsed data to update. |
|
461 * @return {Object} Schema-parsed data. |
|
462 * @static |
|
463 * @protected |
|
464 */ |
|
465 _parseMeta: function(metaFields, xmldoc_in, data_out) { |
|
466 if(LANG.isObject(metaFields)) { |
|
467 var key, |
|
468 xmldoc = xmldoc_in.ownerDocument || xmldoc_in; |
|
469 |
|
470 for(key in metaFields) { |
|
471 if (metaFields.hasOwnProperty(key)) { |
|
472 data_out.meta[key] = SchemaXML._getLocationValue(metaFields[key], xmldoc); |
|
473 } |
|
474 } |
|
475 } |
|
476 return data_out; |
|
477 }, |
|
478 |
|
479 /** |
|
480 * Schema-parsed list of results from full data |
|
481 * |
|
482 * @method _parseResults |
|
483 * @param schema {Object} Schema to parse against. |
|
484 * @param xmldoc_in {Object} XML document parse. |
|
485 * @param data_out {Object} In-progress schema-parsed data to update. |
|
486 * @return {Object} Schema-parsed data. |
|
487 * @static |
|
488 * @protected |
|
489 */ |
|
490 _parseResults: function(schema, xmldoc_in, data_out) { |
|
491 if(schema.resultListLocator && LANG.isArray(schema.resultFields)) { |
|
492 var nodeList = xmldoc_in.getElementsByTagName(schema.resultListLocator), |
|
493 fields = schema.resultFields, |
|
494 results = [], |
|
495 node, field, result, i, j; |
|
496 |
|
497 if(nodeList.length) { |
|
498 // Loop through each result node |
|
499 for(i=nodeList.length-1; i>= 0; i--) { |
|
500 result = {}; |
|
501 node = nodeList[i]; |
|
502 |
|
503 // Find each field value |
|
504 for(j=fields.length-1; j>= 0; j--) { |
|
505 field = fields[j]; |
|
506 result[field.key || field] = SchemaXML._getLocationValue(field, node); |
|
507 } |
|
508 results[i] = result; |
|
509 } |
|
510 |
|
511 data_out.results = results; |
|
512 } |
|
513 else { |
|
514 data_out.error = new Error("XML schema result nodes retrieval failure"); |
|
515 } |
|
516 } |
|
517 return data_out; |
|
518 } |
|
519 }; |
|
520 |
|
521 Y.DataSchema.XML = Y.mix(SchemaXML, Y.DataSchema.Base); |
|
522 |
|
523 |
|
524 |
|
525 }, '3.0.0' ,{requires:['dataschema-base']}); |
|
526 |
|
527 YUI.add('dataschema-array', function(Y) { |
|
528 |
|
529 /** |
|
530 * Provides a DataSchema implementation which can be used to work with data stored in arrays. |
|
531 * |
|
532 * @module dataschema |
|
533 * @submodule dataschema-array |
|
534 */ |
|
535 |
|
536 /** |
|
537 * Array subclass for the DataSchema Utility. |
|
538 * @class DataSchema.Array |
|
539 * @extends DataSchema.Base |
|
540 * @static |
|
541 */ |
|
542 var LANG = Y.Lang, |
|
543 |
|
544 SchemaArray = { |
|
545 |
|
546 ///////////////////////////////////////////////////////////////////////////// |
|
547 // |
|
548 // DataSchema.Array static methods |
|
549 // |
|
550 ///////////////////////////////////////////////////////////////////////////// |
|
551 /** |
|
552 * Applies a given schema to given Array data. |
|
553 * |
|
554 * @method apply |
|
555 * @param schema {Object} Schema to apply. |
|
556 * @param data {Object} Array data. |
|
557 * @return {Object} Schema-parsed data. |
|
558 * @static |
|
559 */ |
|
560 apply: function(schema, data) { |
|
561 var data_in = data, |
|
562 data_out = {results:[],meta:{}}; |
|
563 |
|
564 if(LANG.isArray(data_in)) { |
|
565 if(LANG.isArray(schema.resultFields)) { |
|
566 // Parse results data |
|
567 data_out = SchemaArray._parseResults(schema.resultFields, data_in, data_out); |
|
568 } |
|
569 else { |
|
570 data_out.results = data_in; |
|
571 Y.log("Schema resultFields property not found: " + Y.dump(schema), "warn", "dataschema-array"); |
|
572 } |
|
573 } |
|
574 else { |
|
575 Y.log("Array data could not be schema-parsed: " + Y.dump(data) + " " + Y.dump(data), "error", "dataschema-array"); |
|
576 data_out.error = new Error("Array schema parse failure"); |
|
577 } |
|
578 |
|
579 return data_out; |
|
580 }, |
|
581 |
|
582 /** |
|
583 * Schema-parsed list of results from full data |
|
584 * |
|
585 * @method _parseResults |
|
586 * @param fields {Array} Schema to parse against. |
|
587 * @param array_in {Array} Array to parse. |
|
588 * @param data_out {Object} In-progress parsed data to update. |
|
589 * @return {Object} Parsed data object. |
|
590 * @static |
|
591 * @protected |
|
592 */ |
|
593 _parseResults: function(fields, array_in, data_out) { |
|
594 var results = [], |
|
595 result, item, type, field, key, value, i, j; |
|
596 |
|
597 for(i=array_in.length-1; i>-1; i--) { |
|
598 result = {}; |
|
599 item = array_in[i]; |
|
600 type = (LANG.isObject(item) && !LANG.isFunction(item)) ? 2 : (LANG.isArray(item)) ? 1 : (LANG.isString(item)) ? 0 : -1; |
|
601 if(type > 0) { |
|
602 for(j=fields.length-1; j>-1; j--) { |
|
603 field = fields[j]; |
|
604 key = (!LANG.isUndefined(field.key)) ? field.key : field; |
|
605 value = (!LANG.isUndefined(item[key])) ? item[key] : item[j]; |
|
606 result[key] = Y.DataSchema.Base.parse(value, field); |
|
607 } |
|
608 } |
|
609 else if(type === 0) { |
|
610 result = item; |
|
611 } |
|
612 else { |
|
613 //TODO: null or {}? |
|
614 result = null; |
|
615 Y.log("Unexpected type while parsing array: " + Y.dump(item), "warn", "dataschema-array"); |
|
616 } |
|
617 results[i] = result; |
|
618 } |
|
619 data_out.results = results; |
|
620 |
|
621 return data_out; |
|
622 } |
|
623 }; |
|
624 |
|
625 Y.DataSchema.Array = Y.mix(SchemaArray, Y.DataSchema.Base); |
|
626 |
|
627 |
|
628 |
|
629 }, '3.0.0' ,{requires:['dataschema-base']}); |
|
630 |
|
631 YUI.add('dataschema-text', function(Y) { |
|
632 |
|
633 /** |
|
634 * Provides a DataSchema implementation which can be used to work with delimited text data. |
|
635 * |
|
636 * @module dataschema |
|
637 * @submodule dataschema-text |
|
638 */ |
|
639 |
|
640 /** |
|
641 * Text subclass for the DataSchema Utility. |
|
642 * @class DataSchema.Text |
|
643 * @extends DataSchema.Base |
|
644 * @static |
|
645 */ |
|
646 |
|
647 var LANG = Y.Lang, |
|
648 |
|
649 SchemaText = { |
|
650 |
|
651 ///////////////////////////////////////////////////////////////////////////// |
|
652 // |
|
653 // DataSchema.Text static methods |
|
654 // |
|
655 ///////////////////////////////////////////////////////////////////////////// |
|
656 /** |
|
657 * Applies a given schema to given delimited text data. |
|
658 * |
|
659 * @method apply |
|
660 * @param schema {Object} Schema to apply. |
|
661 * @param data {Object} Text data. |
|
662 * @return {Object} Schema-parsed data. |
|
663 * @static |
|
664 */ |
|
665 apply: function(schema, data) { |
|
666 var data_in = data, |
|
667 data_out = {results:[],meta:{}}; |
|
668 |
|
669 if(LANG.isString(data_in) && LANG.isString(schema.resultDelimiter)) { |
|
670 // Parse results data |
|
671 data_out = SchemaText._parseResults(schema, data_in, data_out); |
|
672 } |
|
673 else { |
|
674 Y.log("Text data could not be schema-parsed: " + Y.dump(data) + " " + Y.dump(data), "error", "dataschema-text"); |
|
675 data_out.error = new Error("Text schema parse failure"); |
|
676 } |
|
677 |
|
678 return data_out; |
|
679 }, |
|
680 |
|
681 /** |
|
682 * Schema-parsed list of results from full data |
|
683 * |
|
684 * @method _parseResults |
|
685 * @param schema {Array} Schema to parse against. |
|
686 * @param text_in {String} Text to parse. |
|
687 * @param data_out {Object} In-progress parsed data to update. |
|
688 * @return {Object} Parsed data object. |
|
689 * @static |
|
690 * @protected |
|
691 */ |
|
692 _parseResults: function(schema, text_in, data_out) { |
|
693 var resultDelim = schema.resultDelimiter, |
|
694 results = [], |
|
695 results_in, fields_in, result, item, fields, field, key, value, i, j, |
|
696 |
|
697 // Delete final delimiter at end of string if there |
|
698 tmpLength = text_in.length-resultDelim.length; |
|
699 if(text_in.substr(tmpLength) == resultDelim) { |
|
700 text_in = text_in.substr(0, tmpLength); |
|
701 } |
|
702 |
|
703 // Split into results |
|
704 results_in = text_in.split(schema.resultDelimiter); |
|
705 |
|
706 for(i=results_in.length-1; i>-1; i--) { |
|
707 result = {}; |
|
708 item = results_in[i]; |
|
709 |
|
710 if(LANG.isString(schema.fieldDelimiter)) { |
|
711 fields_in = item.split(schema.fieldDelimiter); |
|
712 |
|
713 if(LANG.isArray(schema.resultFields)) { |
|
714 fields = schema.resultFields; |
|
715 for(j=fields.length-1; j>-1; j--) { |
|
716 field = fields[j]; |
|
717 key = (!LANG.isUndefined(field.key)) ? field.key : field; |
|
718 value = (!LANG.isUndefined(fields_in[key])) ? fields_in[key] : fields_in[j]; |
|
719 result[key] = Y.DataSchema.Base.parse(value, field); |
|
720 } |
|
721 } |
|
722 |
|
723 } |
|
724 else { |
|
725 result = item; |
|
726 } |
|
727 |
|
728 results[i] = result; |
|
729 } |
|
730 data_out.results = results; |
|
731 |
|
732 return data_out; |
|
733 } |
|
734 }; |
|
735 |
|
736 Y.DataSchema.Text = Y.mix(SchemaText, Y.DataSchema.Base); |
|
737 |
|
738 |
|
739 |
|
740 }, '3.0.0' ,{requires:['dataschema-base']}); |
|
741 |
|
742 |
|
743 |
|
744 YUI.add('dataschema', function(Y){}, '3.0.0' ,{use:['dataschema-base','dataschema-json','dataschema-xml','dataschema-array','dataschema-text']}); |
|
745 |