~launchpad-pqm/lazr-js/toolchain

« back to all changes in this revision

Viewing changes to src-js/lazrjs/yui/dataschema/dataschema-json-debug.js

  • Committer: Sidnei da Silva
  • Date: 2009-11-16 00:51:29 UTC
  • mto: This revision was merged to the branch mainline in revision 154.
  • Revision ID: sidnei.da.silva@canonical.com-20091116005129-8ibwjlboa38glaw5
- Improved generation of skin modules and revamped combo service to make it more twisty.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3
 
Code licensed under the BSD License:
4
 
http://developer.yahoo.com/yui/license.html
5
 
version: 3.2.0
6
 
build: 2676
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(
84
 
                    LANG.isObject(data) &&
85
 
                    (path[i] in data)
86
 
                ) {
87
 
                    data = data[path[i]];
88
 
                }
89
 
                else {
90
 
                    data = undefined;
91
 
                    break;
92
 
                }
93
 
            }
94
 
            return data;
95
 
        },
96
 
 
97
 
        /**
98
 
         * Applies a given schema to given JSON data.
99
 
         *
100
 
         * @method apply
101
 
         * @param schema {Object} Schema to apply.
102
 
         * @param data {Object} JSON data.
103
 
         * @return {Object} Schema-parsed data.
104
 
         * @static
105
 
         */
106
 
        apply: function(schema, data) {
107
 
            var data_in = data,
108
 
                data_out = {results:[],meta:{}};
109
 
 
110
 
            // Convert incoming JSON strings
111
 
            if(!LANG.isObject(data)) {
112
 
                try {
113
 
                    data_in = Y.JSON.parse(data);
114
 
                }
115
 
                catch(e) {
116
 
                    data_out.error = e;
117
 
                    return data_out;
118
 
                }
119
 
            }
120
 
 
121
 
            if(LANG.isObject(data_in) && schema) {
122
 
                // Parse results data
123
 
                if(!LANG.isUndefined(schema.resultListLocator)) {
124
 
                    data_out = SchemaJSON._parseResults.call(this, schema, data_in, data_out);
125
 
                }
126
 
 
127
 
                // Parse meta data
128
 
                if(!LANG.isUndefined(schema.metaFields)) {
129
 
                    data_out = SchemaJSON._parseMeta(schema.metaFields, data_in, data_out);
130
 
                }
131
 
            }
132
 
            else {
133
 
                Y.log("JSON data could not be schema-parsed: " + Y.dump(data) + " " + Y.dump(data), "error", "dataschema-json");
134
 
                data_out.error = new Error("JSON schema parse failure");
135
 
            }
136
 
 
137
 
            return data_out;
138
 
        },
139
 
 
140
 
        /**
141
 
         * Schema-parsed list of results from full data
142
 
         *
143
 
         * @method _parseResults
144
 
         * @param schema {Object} Schema to parse against.
145
 
         * @param json_in {Object} JSON to parse.
146
 
         * @param data_out {Object} In-progress parsed data to update.
147
 
         * @return {Object} Parsed data object.
148
 
         * @static
149
 
         * @protected
150
 
         */
151
 
        _parseResults: function(schema, json_in, data_out) {
152
 
            var results = [],
153
 
                path,
154
 
                error;
155
 
 
156
 
            if(schema.resultListLocator) {
157
 
                path = SchemaJSON.getPath(schema.resultListLocator);
158
 
                if(path) {
159
 
                    results = SchemaJSON.getLocationValue(path, json_in);
160
 
                    if (results === undefined) {
161
 
                        data_out.results = [];
162
 
                        error = new Error("JSON results retrieval failure");
163
 
                    }
164
 
                    else {
165
 
                        if(LANG.isArray(results)) {
166
 
                            // if no result fields are passed in, then just take the results array whole-hog
167
 
                            // Sometimes you're getting an array of strings, or want the whole object,
168
 
                            // so resultFields don't make sense.
169
 
                            if (LANG.isArray(schema.resultFields)) {
170
 
                                data_out = SchemaJSON._getFieldValues.call(this, schema.resultFields, results, data_out);
171
 
                            }
172
 
                            else {
173
 
                                data_out.results = results;
174
 
                            }
175
 
                        }
176
 
                        else {
177
 
                            data_out.results = [];
178
 
                            error = new Error("JSON Schema fields retrieval failure");
179
 
                        }
180
 
                    }
181
 
                }
182
 
                else {
183
 
                    error = new Error("JSON Schema results locator failure");
184
 
                }
185
 
 
186
 
                if (error) {
187
 
                    Y.log("JSON data could not be parsed: " + Y.dump(json_in), "error", "dataschema-json");
188
 
                    data_out.error = error;
189
 
                }
190
 
 
191
 
            }
192
 
            return data_out;
193
 
        },
194
 
 
195
 
        /**
196
 
         * Get field data values out of list of full results
197
 
         *
198
 
         * @method _getFieldValues
199
 
         * @param fields {Array} Fields to find.
200
 
         * @param array_in {Array} Results to parse.
201
 
         * @param data_out {Object} In-progress parsed data to update.
202
 
         * @return {Object} Parsed data object.
203
 
         * @static
204
 
         * @protected
205
 
         */
206
 
        _getFieldValues: function(fields, array_in, data_out) {
207
 
            var results = [],
208
 
                len = fields.length,
209
 
                i, j,
210
 
                field, key, path, parser,
211
 
                simplePaths = [], complexPaths = [], fieldParsers = [],
212
 
                result, record;
213
 
 
214
 
            // First collect hashes of simple paths, complex paths, and parsers
215
 
            for (i=0; i<len; i++) {
216
 
                field = fields[i]; // A field can be a simple string or a hash
217
 
                key = field.key || field; // Find the key
218
 
 
219
 
                // Validate and store locators for later
220
 
                path = SchemaJSON.getPath(key);
221
 
                if (path) {
222
 
                    if (path.length === 1) {
223
 
                        simplePaths[simplePaths.length] = {key:key, path:path[0]};
224
 
                    } else {
225
 
                        complexPaths[complexPaths.length] = {key:key, path:path};
226
 
                    }
227
 
                } else {
228
 
                    Y.log("Invalid key syntax: " + key, "warn", "dataschema-json");
229
 
                }
230
 
 
231
 
                // Validate and store parsers for later
232
 
                //TODO: use Y.DataSchema.parse?
233
 
                parser = (LANG.isFunction(field.parser)) ? field.parser : Y.Parsers[field.parser+''];
234
 
                if (parser) {
235
 
                    fieldParsers[fieldParsers.length] = {key:key, parser:parser};
236
 
                }
237
 
            }
238
 
 
239
 
            // Traverse list of array_in, creating records of simple fields,
240
 
            // complex fields, and applying parsers as necessary
241
 
            for (i=array_in.length-1; i>=0; --i) {
242
 
                record = {};
243
 
                result = array_in[i];
244
 
                if(result) {
245
 
                    // Cycle through simpleLocators
246
 
                    for (j=simplePaths.length-1; j>=0; --j) {
247
 
                        // Bug 1777850: The result might be an array instead of object
248
 
                        record[simplePaths[j].key] = Y.DataSchema.Base.parse.call(this,
249
 
                                (LANG.isUndefined(result[simplePaths[j].path]) ?
250
 
                                result[j] : result[simplePaths[j].path]), simplePaths[j]);
251
 
                    }
252
 
 
253
 
                    // Cycle through complexLocators
254
 
                    for (j=complexPaths.length - 1; j>=0; --j) {
255
 
                        record[complexPaths[j].key] = Y.DataSchema.Base.parse.call(this,
256
 
                            (SchemaJSON.getLocationValue(complexPaths[j].path, result)), complexPaths[j] );
257
 
                    }
258
 
 
259
 
                    // Cycle through fieldParsers
260
 
                    for (j=fieldParsers.length-1; j>=0; --j) {
261
 
                        key = fieldParsers[j].key;
262
 
                        record[key] = fieldParsers[j].parser.call(this, record[key]);
263
 
                        // Safety net
264
 
                        if (LANG.isUndefined(record[key])) {
265
 
                            record[key] = null;
266
 
                        }
267
 
                    }
268
 
                    results[i] = record;
269
 
                }
270
 
            }
271
 
            data_out.results = results;
272
 
            return data_out;
273
 
        },
274
 
 
275
 
        /**
276
 
         * Parses results data according to schema
277
 
         *
278
 
         * @method _parseMeta
279
 
         * @param metaFields {Object} Metafields definitions.
280
 
         * @param json_in {Object} JSON to parse.
281
 
         * @param data_out {Object} In-progress parsed data to update.
282
 
         * @return {Object} Schema-parsed meta data.
283
 
         * @static
284
 
         * @protected
285
 
         */
286
 
        _parseMeta: function(metaFields, json_in, data_out) {
287
 
            if(LANG.isObject(metaFields)) {
288
 
                var key, path;
289
 
                for(key in metaFields) {
290
 
                    if (metaFields.hasOwnProperty(key)) {
291
 
                        path = SchemaJSON.getPath(metaFields[key]);
292
 
                        if (path && json_in) {
293
 
                            data_out.meta[key] = SchemaJSON.getLocationValue(path, json_in);
294
 
                        }
295
 
                    }
296
 
                }
297
 
            }
298
 
            else {
299
 
                data_out.error = new Error("JSON meta data retrieval failure");
300
 
            }
301
 
            return data_out;
302
 
        }
303
 
    };
304
 
 
305
 
Y.DataSchema.JSON = Y.mix(SchemaJSON, Y.DataSchema.Base);
306
 
 
307
 
 
308
 
 
309
 
}, '3.2.0' ,{requires:['json', 'dataschema-base']});